aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeff Walsh2019-06-15 14:44:47 +1000
committerJeff Walsh2020-11-22 14:46:55 +1100
commitcdc04b4509772f2324c4ca63732caed2858cedf3 (patch)
tree4c25236482f6faedb806dca4040c098a1364e96c /src
parent12cc104cd54dd80a9bc1d391a256de49f4b77077 (diff)
downloademacs-cdc04b4509772f2324c4ca63732caed2858cedf3.tar.gz
emacs-cdc04b4509772f2324c4ca63732caed2858cedf3.zip
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):
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c1
-rw-r--r--src/lisp.h2
-rw-r--r--src/menu.h6
-rw-r--r--src/pgtkfns.c117
-rw-r--r--src/pgtkmenu.c476
-rw-r--r--src/pgtkterm.c11
-rw-r--r--src/pgtkterm.h6
-rw-r--r--src/xdisp.c5
8 files changed, 541 insertions, 83 deletions
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
1921 syms_of_pgtkterm(); 1921 syms_of_pgtkterm();
1922 syms_of_pgtkfns(); 1922 syms_of_pgtkfns();
1923 syms_of_pgtkselect (); 1923 syms_of_pgtkselect ();
1924 syms_of_pgtkmenu ();
1924 syms_of_fontset (); 1925 syms_of_fontset ();
1925 syms_of_xsettings (); 1926 syms_of_xsettings ();
1926 syms_of_xwidget (); 1927 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;
3298#endif 3298#endif
3299 3299
3300/* Define if the windowing system provides a tool-bar. */ 3300/* Define if the windowing system provides a tool-bar. */
3301#if (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) 3301#if defined (USE_GTK) || defined (HAVE_NS)
3302#define HAVE_EXT_TOOL_BAR true 3302#define HAVE_EXT_TOOL_BAR true
3303#endif 3303#endif
3304 3304
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,
59 Lisp_Object, const char **); 59 Lisp_Object, const char **);
60extern void ns_activate_menubar (struct frame *); 60extern void ns_activate_menubar (struct frame *);
61#endif 61#endif
62#ifdef HAVE_PGTK
63extern Lisp_Object pgtk_menu_show (struct frame *, int, int, int,
64 Lisp_Object, const char **);
65extern void pgtk_activate_menubar (struct frame *);
66#endif
67
62extern Lisp_Object tty_menu_show (struct frame *, int, int, int, 68extern Lisp_Object tty_menu_show (struct frame *, int, int, int,
63 Lisp_Object, const char **); 69 Lisp_Object, const char **);
64extern ptrdiff_t menu_item_width (const unsigned char *); 70extern 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)
465static void 465static void
466x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) 466x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
467{ 467{
468#if 0
469 int nlines; 468 int nlines;
470 if (FRAME_MINIBUF_ONLY_P (f)) 469 /* Right now, menu bars don't work properly in minibuf-only frames;
470 most of the commands try to apply themselves to the minibuffer
471 frame itself, and get an error because you can't switch buffers
472 in or split the minibuffer window. */
473 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
471 return; 474 return;
472 475
473 if (TYPE_RANGED_INTEGERP (int, value)) 476 if (TYPE_RANGED_FIXNUMP (int, value))
474 nlines = XFIXNUM (value); 477 nlines = XFIXNUM (value);
475 else 478 else
476 nlines = 0; 479 nlines = 0;
477 480
481 /* Make sure we redisplay all windows in this frame. */
482 fset_redisplay (f);
483
478 FRAME_MENU_BAR_LINES (f) = 0; 484 FRAME_MENU_BAR_LINES (f) = 0;
485 FRAME_MENU_BAR_HEIGHT (f) = 0;
479 if (nlines) 486 if (nlines)
480 { 487 {
481 FRAME_EXTERNAL_MENU_BAR (f) = 1; 488 FRAME_EXTERNAL_MENU_BAR (f) = 1;
482 /* does for all frames, whereas we just want for one frame 489 if (FRAME_PGTK_P (f) && f->output_data.pgtk->menubar_widget == 0)
483 [NSMenu setMenuBarVisible: YES]; */ 490 /* Make sure next redisplay shows the menu bar. */
491 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
484 } 492 }
485 else 493 else
486 { 494 {
487 if (FRAME_EXTERNAL_MENU_BAR (f) == 1) 495 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
488 free_frame_menubar (f); 496 free_frame_menubar (f);
489 /* [NSMenu setMenuBarVisible: NO]; */
490 FRAME_EXTERNAL_MENU_BAR (f) = 0; 497 FRAME_EXTERNAL_MENU_BAR (f) = 0;
498 if (FRAME_X_P (f))
499 f->output_data.pgtk->menubar_widget = 0;
500 }
501
502 adjust_frame_glyphs (f);
503}
504
505/* Set the pixel height of the tool bar of frame F to HEIGHT. */
506static void
507x_change_tool_bar_height (struct frame *f, int height)
508{
509 FRAME_TOOL_BAR_LINES (f) = 0;
510 FRAME_TOOL_BAR_HEIGHT (f) = 0;
511 if (height)
512 {
513 FRAME_EXTERNAL_TOOL_BAR (f) = true;
514 if (FRAME_X_P (f) && f->output_data.pgtk->toolbar_widget == 0)
515 /* Make sure next redisplay shows the tool bar. */
516 XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
517 update_frame_tool_bar (f);
518 }
519 else
520 {
521 if (FRAME_EXTERNAL_TOOL_BAR (f))
522 free_frame_tool_bar (f);
523 FRAME_EXTERNAL_TOOL_BAR (f) = false;
491 } 524 }
492#endif
493} 525}
494 526
495 527
@@ -497,70 +529,20 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
497static void 529static void
498x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) 530x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
499{ 531{
500#if 0
501 /* Currently, when the tool bar change state, the frame is resized.
502
503 TODO: It would be better if this didn't occur when 1) the frame
504 is full height or maximized or 2) when specified by
505 `frame-inhibit-implied-resize'. */
506 int nlines; 532 int nlines;
507 533
508 NSTRACE ("x_set_tool_bar_lines"); 534 /* Treat tool bars like menu bars. */
509
510 if (FRAME_MINIBUF_ONLY_P (f)) 535 if (FRAME_MINIBUF_ONLY_P (f))
511 return; 536 return;
512 537
513 if (RANGED_INTEGERP (0, value, INT_MAX)) 538 /* Use VALUE only if an int >= 0. */
539 if (RANGED_FIXNUMP (0, value, INT_MAX))
514 nlines = XFIXNAT (value); 540 nlines = XFIXNAT (value);
515 else 541 else
516 nlines = 0; 542 nlines = 0;
517 543
518 if (nlines) 544 x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
519 {
520 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
521 update_frame_tool_bar (f);
522 }
523 else
524 {
525 if (FRAME_EXTERNAL_TOOL_BAR (f))
526 {
527 free_frame_tool_bar (f);
528 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
529
530 {
531 EmacsView *view = FRAME_PGTK_VIEW (f);
532 int fs_state = [view fullscreenState];
533
534 if (fs_state == FULLSCREEN_MAXIMIZED)
535 {
536 [view setFSValue:FULLSCREEN_WIDTH];
537 }
538 else if (fs_state == FULLSCREEN_HEIGHT)
539 {
540 [view setFSValue:FULLSCREEN_NONE];
541 }
542 }
543 }
544 }
545 545
546 {
547 int inhibit
548 = ((f->after_make_frame
549 && !f->tool_bar_resized
550 && (EQ (frame_inhibit_implied_resize, Qt)
551 || (CONSP (frame_inhibit_implied_resize)
552 && !NILP (Fmemq (Qtool_bar_lines,
553 frame_inhibit_implied_resize))))
554 && NILP (get_frame_param (f, Qfullscreen)))
555 ? 0
556 : 2);
557
558 NSTRACE_MSG ("inhibit:%d", inhibit);
559
560 frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
561 adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
562 }
563#endif
564} 546}
565 547
566 548
@@ -1327,25 +1309,14 @@ This function is an internal primitive--use `make-frame' instead. */)
1327 gui_default_parameter (f, parms, Qno_accept_focus, Qnil, 1309 gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
1328 NULL, NULL, RES_TYPE_BOOLEAN); 1310 NULL, NULL, RES_TYPE_BOOLEAN);
1329 1311
1330#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1331 /* Create the menu bar. */ 1312 /* Create the menu bar. */
1332 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 1313 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
1333 { 1314 {
1334#if 0
1335 /* If this signals an error, we haven't set size hints for the 1315 /* If this signals an error, we haven't set size hints for the
1336 frame and we didn't make it visible. */ 1316 frame and we didn't make it visible. */
1337 initialize_frame_menubar (f); 1317 initialize_frame_menubar (f);
1338#endif
1339 1318
1340#ifndef USE_GTK
1341 /* This is a no-op, except under Motif where it arranges the
1342 main window for the widgets on it. */
1343 lw_set_main_areas (FRAME_X_OUTPUT(f)->column_widget,
1344 FRAME_X_OUTPUT(f)->menubar_widget,
1345 FRAME_X_OUTPUT(f)->edit_widget);
1346#endif /* not USE_GTK */
1347 } 1319 }
1348#endif /* USE_X_TOOLKIT || USE_GTK */
1349 1320
1350 /* Consider frame official, now. */ 1321 /* Consider frame official, now. */
1351 f->can_set_window_size = true; 1322 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 @@
1/* Pure GTK3 menu and toolbar module.
2 Copyright (C) 2019 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or (at
9your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
18
19/*
20 */
21
22
23/* This should be the first include, as it may set up #defines affecting
24 interpretation of even the system includes. */
25#include <config.h>
26
27#include "lisp.h"
28#include "frame.h"
29#include "window.h"
30#include "character.h"
31#include "buffer.h"
32#include "keymap.h"
33#include "coding.h"
34#include "commands.h"
35#include "blockinput.h"
36#include "termhooks.h"
37#include "keyboard.h"
38#include "menu.h"
39#include "pdumper.h"
40
41#include "gtkutil.h"
42#include <gtk/gtk.h>
43
44
45Lisp_Object
46pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
47{
48 return Qnil;
49}
50
51
52
53/* Gtk calls callbacks just because we tell it what item should be
54 selected in a radio group. If this variable is set to a non-zero
55 value, we are creating menus and don't want callbacks right now.
56*/
57static bool xg_crazy_callback_abort;
58
59/* This callback is called from the menu bar pulldown menu
60 when the user makes a selection.
61 Figure out what the user chose
62 and put the appropriate events into the keyboard buffer. */
63static void
64menubar_selection_callback (GtkWidget *widget, gpointer client_data)
65{
66 xg_menu_item_cb_data *cb_data = client_data;
67
68 if (xg_crazy_callback_abort)
69 return;
70
71 if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
72 return;
73
74 /* For a group of radio buttons, GTK calls the selection callback first
75 for the item that was active before the selection and then for the one that
76 is active after the selection. For C-h k this means we get the help on
77 the deselected item and then the selected item is executed. Prevent that
78 by ignoring the non-active item. */
79 if (GTK_IS_RADIO_MENU_ITEM (widget)
80 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
81 return;
82
83 /* When a menu is popped down, X generates a focus event (i.e. focus
84 goes back to the frame below the menu). Since GTK buffers events,
85 we force it out here before the menu selection event. Otherwise
86 sit-for will exit at once if the focus event follows the menu selection
87 event. */
88
89 block_input ();
90 while (gtk_events_pending ())
91 gtk_main_iteration ();
92 unblock_input ();
93
94 find_and_call_menu_selection (cb_data->cl_data->f,
95 cb_data->cl_data->menu_bar_items_used,
96 cb_data->cl_data->menu_bar_vector,
97 cb_data->call_data);
98}
99
100static void
101menu_highlight_callback (GtkWidget *widget, gpointer call_data)
102{
103 xg_menu_item_cb_data *cb_data;
104 Lisp_Object help;
105
106 cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA);
107 if (! cb_data) return;
108
109 help = call_data ? cb_data->help : Qnil;
110}
111
112
113/* This callback is invoked when a dialog or menu is finished being
114 used and has been unposted. */
115
116static void
117popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
118{
119}
120
121
122
123
124/* Set the contents of the menubar widgets of frame F.
125 The argument FIRST_TIME is currently ignored;
126 it is set the first time this is called, from initialize_frame_menubar. */
127
128void
129set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
130{
131 GtkWidget * menubar_widget;
132 Lisp_Object items;
133 widget_value *wv, *first_wv, *prev_wv = 0;
134 int i;
135 int *submenu_start, *submenu_end;
136 bool *submenu_top_level_items;
137 int *submenu_n_panes;
138
139
140 menubar_widget = f->output_data.pgtk->menubar_widget;
141
142 XSETFRAME(Vmenu_updating_frame, f);
143
144 if (! menubar_widget)
145 deep_p = true;
146
147 if (deep_p)
148 {
149 struct buffer *prev = current_buffer;
150 Lisp_Object buffer;
151 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
152 int previous_menu_items_used = f->menu_bar_items_used;
153 Lisp_Object *previous_items
154 = alloca (previous_menu_items_used * sizeof *previous_items);
155 int subitems;
156
157 /* If we are making a new widget, its contents are empty,
158 do always reinitialize them. */
159 if (! menubar_widget)
160 previous_menu_items_used = 0;
161
162 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
163 specbind (Qinhibit_quit, Qt);
164 /* Don't let the debugger step into this code
165 because it is not reentrant. */
166 specbind (Qdebug_on_next_call, Qnil);
167
168 record_unwind_save_match_data ();
169 if (NILP (Voverriding_local_map_menu_flag))
170 {
171 specbind (Qoverriding_terminal_local_map, Qnil);
172 specbind (Qoverriding_local_map, Qnil);
173 }
174
175 set_buffer_internal_1 (XBUFFER (buffer));
176
177 /* Run the Lucid hook. */
178 safe_run_hooks (Qactivate_menubar_hook);
179
180 /* If it has changed current-menubar from previous value,
181 really recompute the menubar from the value. */
182 if (! NILP (Vlucid_menu_bar_dirty_flag))
183 call0 (Qrecompute_lucid_menubar);
184 safe_run_hooks (Qmenu_bar_update_hook);
185 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
186
187 items = FRAME_MENU_BAR_ITEMS (f);
188
189 /* Save the frame's previous menu bar contents data. */
190 if (previous_menu_items_used)
191 memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
192 previous_menu_items_used * word_size);
193
194 /* Fill in menu_items with the current menu bar contents.
195 This can evaluate Lisp code. */
196 save_menu_items ();
197
198 menu_items = f->menu_bar_vector;
199 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
200 subitems = ASIZE (items) / 4;
201 submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
202 submenu_end = alloca (subitems * sizeof *submenu_end);
203 submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
204 submenu_top_level_items = alloca (subitems
205 * sizeof *submenu_top_level_items);
206 init_menu_items ();
207 for (i = 0; i < subitems; i++)
208 {
209 Lisp_Object key, string, maps;
210
211 key = AREF (items, 4 * i);
212 string = AREF (items, 4 * i + 1);
213 maps = AREF (items, 4 * i + 2);
214 if (NILP (string))
215 break;
216
217 submenu_start[i] = menu_items_used;
218
219 menu_items_n_panes = 0;
220 submenu_top_level_items[i]
221 = parse_single_submenu (key, string, maps);
222 submenu_n_panes[i] = menu_items_n_panes;
223
224 submenu_end[i] = menu_items_used;
225 }
226
227 submenu_start[i] = -1;
228 finish_menu_items ();
229
230 /* Convert menu_items into widget_value trees
231 to display the menu. This cannot evaluate Lisp code. */
232
233 wv = make_widget_value ("menubar", NULL, true, Qnil);
234 wv->button_type = BUTTON_TYPE_NONE;
235 first_wv = wv;
236
237 for (i = 0; submenu_start[i] >= 0; i++)
238 {
239 menu_items_n_panes = submenu_n_panes[i];
240 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
241 submenu_top_level_items[i]);
242 if (prev_wv)
243 prev_wv->next = wv;
244 else
245 first_wv->contents = wv;
246 /* Don't set wv->name here; GC during the loop might relocate it. */
247 wv->enabled = true;
248 wv->button_type = BUTTON_TYPE_NONE;
249 prev_wv = wv;
250 }
251
252 set_buffer_internal_1 (prev);
253
254 /* If there has been no change in the Lisp-level contents
255 of the menu bar, skip redisplaying it. Just exit. */
256
257 /* Compare the new menu items with the ones computed last time. */
258 for (i = 0; i < previous_menu_items_used; i++)
259 if (menu_items_used == i
260 || (!EQ (previous_items[i], AREF (menu_items, i))))
261 break;
262 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
263 {
264 /* The menu items have not changed. Don't bother updating
265 the menus in any form, since it would be a no-op. */
266 free_menubar_widget_value_tree (first_wv);
267 discard_menu_items ();
268 unbind_to (specpdl_count, Qnil);
269 return;
270 }
271
272 /* The menu items are different, so store them in the frame. */
273 fset_menu_bar_vector (f, menu_items);
274 f->menu_bar_items_used = menu_items_used;
275
276 /* This undoes save_menu_items. */
277 unbind_to (specpdl_count, Qnil);
278
279 /* Now GC cannot happen during the lifetime of the widget_value,
280 so it's safe to store data from a Lisp_String. */
281 wv = first_wv->contents;
282 for (i = 0; i < ASIZE (items); i += 4)
283 {
284 Lisp_Object string;
285 string = AREF (items, i + 1);
286 if (NILP (string))
287 break;
288 wv->name = SSDATA (string);
289 update_submenu_strings (wv->contents);
290 wv = wv->next;
291 }
292
293 }
294 else
295 {
296 /* Make a widget-value tree containing
297 just the top level menu bar strings. */
298
299 wv = make_widget_value ("menubar", NULL, true, Qnil);
300 wv->button_type = BUTTON_TYPE_NONE;
301 first_wv = wv;
302
303 items = FRAME_MENU_BAR_ITEMS (f);
304 for (i = 0; i < ASIZE (items); i += 4)
305 {
306 Lisp_Object string;
307
308 string = AREF (items, i + 1);
309 if (NILP (string))
310 break;
311
312 wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
313 wv->button_type = BUTTON_TYPE_NONE;
314 /* This prevents lwlib from assuming this
315 menu item is really supposed to be empty. */
316 /* The intptr_t cast avoids a warning.
317 This value just has to be different from small integers. */
318 wv->call_data = (void *) (intptr_t) (-1);
319
320 if (prev_wv)
321 prev_wv->next = wv;
322 else
323 first_wv->contents = wv;
324 prev_wv = wv;
325 }
326
327 /* Forget what we thought we knew about what is in the
328 detailed contents of the menu bar menus.
329 Changing the top level always destroys the contents. */
330 f->menu_bar_items_used = 0;
331 }
332
333 block_input();
334
335 xg_crazy_callback_abort = true;
336 if (menubar_widget)
337 {
338 /* The fourth arg is DEEP_P, which says to consider the entire
339 menu trees we supply, rather than just the menu bar item names. */
340 xg_modify_menubar_widgets (menubar_widget,
341 f,
342 first_wv,
343 deep_p,
344 G_CALLBACK (menubar_selection_callback),
345 G_CALLBACK (popup_deactivate_callback),
346 G_CALLBACK (menu_highlight_callback));
347 }
348 else
349 {
350 menubar_widget
351 = xg_create_widget ("menubar", "menubar", f, first_wv,
352 G_CALLBACK (menubar_selection_callback),
353 G_CALLBACK (popup_deactivate_callback),
354 G_CALLBACK (menu_highlight_callback));
355
356 f->output_data.pgtk->menubar_widget = menubar_widget;
357 }
358
359 free_menubar_widget_value_tree (first_wv);
360 xg_update_frame_menubar (f);
361
362 xg_crazy_callback_abort = false;
363
364 unblock_input ();
365}
366
367
368
369/* Called from Fx_create_frame to create the initial menubar of a frame
370 before it is mapped, so that the window is mapped with the menubar already
371 there instead of us tacking it on later and thrashing the window after it
372 is visible. */
373
374void
375initialize_frame_menubar (struct frame *f)
376{
377 /* This function is called before the first chance to redisplay
378 the frame. It has to be, so the frame will have the right size. */
379 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
380 set_frame_menubar (f, true, true);
381}
382
383
384void pgtk_activate_menubar (struct frame *f)
385{
386 set_frame_menubar(f, false, false);
387
388 /* f->output_data.pgtk->menubar_active = 1; */
389}
390
391
392Lisp_Object
393pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
394 Lisp_Object title, const char **error_name)
395{
396 Lisp_Object tem;
397
398 block_input ();
399
400
401 unblock_input ();
402
403 // not implemented.
404 return Qnil;
405}
406
407DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
408 doc: /* Start key navigation of the menu bar in FRAME.
409This initially opens the first menu bar item and you can then navigate with the
410arrow keys, select a menu entry with the return key or cancel with the
411escape key. If FRAME has no menu bar this function does nothing.
412
413If FRAME is nil or not given, use the selected frame. */)
414 (Lisp_Object frame)
415{
416 GtkWidget *menubar;
417 struct frame *f;
418
419 block_input ();
420 f = decode_window_system_frame (frame);
421
422 if (FRAME_EXTERNAL_MENU_BAR (f))
423 set_frame_menubar (f, false, true);
424
425 menubar = FRAME_X_OUTPUT (f)->menubar_widget;
426 if (menubar)
427 {
428 /* Activate the first menu. */
429 GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
430
431 if (children)
432 {
433 g_signal_emit_by_name (children->data, "activate_item");
434 g_list_free (children);
435 }
436 }
437 unblock_input ();
438
439 return Qnil;
440}
441
442
443static const char * button_names [] = {
444 "button1", "button2", "button3", "button4", "button5",
445 "button6", "button7", "button8", "button9", "button10" };
446
447extern Lisp_Object
448pgtk_dialog_show (struct frame *f, Lisp_Object title,
449 Lisp_Object header, char **error)
450{
451 return Qnil;
452}
453
454/* The following is used by delayed window autoselection. */
455
456DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
457 doc: /* SKIP: real doc in xmenu.c. */)
458 (void)
459{
460 struct frame *f;
461 f = SELECTED_FRAME ();
462 // return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil;
463 return Qnil;
464}
465
466void
467syms_of_pgtkmenu (void)
468{
469 // current_popup_menu = NULL;
470 // PDUMPER_IGNORE (current_popup_menu);
471
472 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
473 DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog");
474
475 defsubr (&Smenu_or_popup_active_p);
476}
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)
4253 } 4253 }
4254} 4254}
4255 4255
4256static Lisp_Object
4257pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
4258 Lisp_Object title, const char **error_name)
4259{
4260 // not implemented.
4261 return Qnil;
4262}
4263
4264/* This function is called when the last frame on a display is deleted. */ 4256/* This function is called when the last frame on a display is deleted. */
4265void 4257void
4266pgtk_delete_terminal (struct terminal *terminal) 4258pgtk_delete_terminal (struct terminal *terminal)
@@ -4332,7 +4324,8 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
4332 // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; 4324 // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower;
4333 terminal->fullscreen_hook = pgtk_fullscreen_hook; 4325 terminal->fullscreen_hook = pgtk_fullscreen_hook;
4334 terminal->menu_show_hook = pgtk_menu_show; 4326 terminal->menu_show_hook = pgtk_menu_show;
4335 // terminal->popup_dialog_hook = pgtk_popup_dialog; 4327 terminal->activate_menubar_hook = pgtk_activate_menubar;
4328 terminal->popup_dialog_hook = pgtk_popup_dialog;
4336 terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar; 4329 terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar;
4337 terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar; 4330 terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar;
4338 terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars; 4331 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)
548extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); 548extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f);
549extern void pgtk_cr_destroy_surface(struct frame *f); 549extern void pgtk_cr_destroy_surface(struct frame *f);
550 550
551/* Defined in pgtkmenu.c */
552extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents);
553extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object header, char **error);
554extern void initialize_frame_menubar (struct frame *);
555
556
551/* Symbol initializations implemented in each pgtk sources. */ 557/* Symbol initializations implemented in each pgtk sources. */
552extern void syms_of_pgtkterm (void); 558extern void syms_of_pgtkterm (void);
553extern void syms_of_pgtkfns (void); 559extern 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)
25028 if (FRAME_W32_P (f)) 25028 if (FRAME_W32_P (f))
25029 return; 25029 return;
25030#endif 25030#endif
25031#if defined (HAVE_PGTK)
25032 if (FRAME_PGTK_P (f))
25033 return;
25034#endif
25035
25031#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 25036#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
25032 if (FRAME_X_P (f)) 25037 if (FRAME_X_P (f))
25033 return; 25038 return;