From: Eli Zaretskii Date: Sun, 29 Sep 2013 18:38:56 +0000 (+0300) Subject: x-popup-dialog fixed, almost. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1328^2~21 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0afa0aabd833fff2e8da06e24da6c4bab7aadec3;p=emacs.git x-popup-dialog fixed, almost. --- diff --git a/src/menu.c b/src/menu.c index 5ca687f3d8a..7c34a9cacd4 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1376,6 +1376,141 @@ no quit occurs and `x-popup-menu' returns nil. */) return selection; } +#ifdef HAVE_MENUS + +DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, + doc: /* Pop up a dialog box and return user's selection. +POSITION specifies which frame to use. +This is normally a mouse button event or a window or frame. +If POSITION is t, it means to use the frame the mouse is on. +The dialog box appears in the middle of the specified frame. + +CONTENTS specifies the alternatives to display in the dialog box. +It is a list of the form (DIALOG ITEM1 ITEM2...). +Each ITEM is a cons cell (STRING . VALUE). +The return value is VALUE from the chosen item. + +An ITEM may also be just a string--that makes a nonselectable item. +An ITEM may also be nil--that means to put all preceding items +on the left of the dialog box and all following items on the right. +\(By default, approximately half appear on each side.) + +If HEADER is non-nil, the frame title for the box is "Information", +otherwise it is "Question". + +If the user gets rid of the dialog box without making a valid choice, +for instance using the window manager, then this produces a quit and +`x-popup-dialog' does not return. */) + (Lisp_Object position, Lisp_Object contents, Lisp_Object header) +{ + struct frame *f = NULL; + Lisp_Object window; + + /* Decode the first argument: find the window or frame to use. */ + if (EQ (position, Qt) + || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) + || EQ (XCAR (position), Qtool_bar)))) + { +#if 0 /* Using the frame the mouse is on may not be right. */ + /* Use the mouse's current position. */ + struct frame *new_f = SELECTED_FRAME (); + Lisp_Object bar_window; + enum scroll_bar_part part; + Time time; + Lisp_Object x, y; + + (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); + + if (new_f != 0) + XSETFRAME (window, new_f); + else + window = selected_window; +#endif + window = selected_window; + } + else if (CONSP (position)) + { + Lisp_Object tem = XCAR (position); + if (CONSP (tem)) + window = Fcar (XCDR (position)); + else + { + tem = Fcar (XCDR (position)); /* EVENT_START (position) */ + window = Fcar (tem); /* POSN_WINDOW (tem) */ + } + } + else if (WINDOWP (position) || FRAMEP (position)) + window = position; + else + window = Qnil; + + /* Decode where to put the menu. */ + + if (FRAMEP (window)) + f = XFRAME (window); + else if (WINDOWP (window)) + { + CHECK_LIVE_WINDOW (window); + f = XFRAME (WINDOW_FRAME (XWINDOW (window))); + } + else + /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, + but I don't want to make one now. */ + CHECK_WINDOW (window); + + /* Force a redisplay before showing the dialog. If a frame is created + just before showing the dialog, its contents may not have been fully + drawn, as this depends on timing of events from the X server. Redisplay + is not done when a dialog is shown. If redisplay could be done in the + X event loop (i.e. the X event loop does not run in a signal handler) + this would not be needed. + + Do this before creating the widget value that points to Lisp + string contents, because Fredisplay may GC and relocate them. */ + Fredisplay (Qt); +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + if (FRAME_WINDOW_P (f)) + return xw_popup_dialog (f, header, contents); + else +#endif +#if defined (HAVE_NTGUI) && defined (HAVE_DIALOGS) + if (FRAME_W32_P (f)) + return w32_popup_dialog (f, header, contents); + else +#endif +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + return ns_popup_dialog (position, header, contents); + else +#endif + /* Display a menu with these alternatives + in the middle of frame F. */ + { + Lisp_Object x, y, frame, newpos; + int frame_width, frame_height; + + if (FRAME_WINDOW_P (f)) + { + frame_width = FRAME_PIXEL_WIDTH (f); + frame_height = FRAME_PIXEL_HEIGHT (f); + } + else + { + frame_width = FRAME_COLS (f); + frame_height = FRAME_LINES (f); + } + XSETFRAME (frame, f); + XSETINT (x, frame_width / 2); + XSETINT (y, frame_height / 2); + newpos = list2 (list2 (x, y), frame); + + return Fx_popup_menu (newpos, + list2 (Fcar (contents), contents)); + } +} + +#endif /* HAVE_MENUS */ + void syms_of_menu (void) { @@ -1384,4 +1519,8 @@ syms_of_menu (void) menu_items_inuse = Qnil; defsubr (&Sx_popup_menu); + +#ifdef HAVE_MENUS + defsubr (&Sx_popup_dialog); +#endif } diff --git a/src/nsmenu.m b/src/nsmenu.m index 3ed1734d222..19f161709d1 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1452,7 +1452,7 @@ pop_down_menu (void *arg) Lisp_Object -ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) +ns_popup_dialog (Lisp_Object position, Lisp_Object header, Lisp_Object contents) { id dialog; Lisp_Object window, tem, title; @@ -1919,34 +1919,6 @@ DEFUN ("ns-reset-menu", Fns_reset_menu, Sns_reset_menu, 0, 0, 0, } -DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, - doc: /* Pop up a dialog box and return user's selection. -POSITION specifies which frame to use. -This is normally a mouse button event or a window or frame. -If POSITION is t, it means to use the frame the mouse is on. -The dialog box appears in the middle of the specified frame. - -CONTENTS specifies the alternatives to display in the dialog box. -It is a list of the form (DIALOG ITEM1 ITEM2...). -Each ITEM is a cons cell (STRING . VALUE). -The return value is VALUE from the chosen item. - -An ITEM may also be just a string--that makes a nonselectable item. -An ITEM may also be nil--that means to put all preceding items -on the left of the dialog box and all following items on the right. -\(By default, approximately half appear on each side.) - -If HEADER is non-nil, the frame title for the box is "Information", -otherwise it is "Question". - -If the user gets rid of the dialog box without making a valid choice, -for instance using the window manager, then this produces a quit and -`x-popup-dialog' does not return. */) - (Lisp_Object position, Lisp_Object contents, Lisp_Object header) -{ - return ns_popup_dialog (position, contents, header); -} - DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0, doc: /* Return t if a menu or popup dialog is active. */) (void) @@ -1968,7 +1940,6 @@ syms_of_nsmenu (void) update menus there. */ trackingMenu = 1; #endif - defsubr (&Sx_popup_dialog); defsubr (&Sns_reset_menu); defsubr (&Smenu_or_popup_active_p); diff --git a/src/nsterm.h b/src/nsterm.h index 9f7767b312e..198a8867545 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -850,8 +850,8 @@ extern void find_and_call_menu_selection (struct frame *f, extern Lisp_Object find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data); -extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents, - Lisp_Object header); +extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object header, + Lisp_Object contents); #define NSAPP_DATA2_RUNASSCRIPT 10 extern void ns_run_ascript (void); diff --git a/src/w32menu.c b/src/w32menu.c index ad2eb96495a..6ac02d95a63 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -115,129 +115,34 @@ static int fill_in_menu (HMENU, widget_value *); void w32_free_menu_strings (HWND); #ifdef HAVE_MENUS - -DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, - doc: /* Pop up a dialog box and return user's selection. -POSITION specifies which frame to use. -This is normally a mouse button event or a window or frame. -If POSITION is t, it means to use the frame the mouse is on. -The dialog box appears in the middle of the specified frame. - -CONTENTS specifies the alternatives to display in the dialog box. -It is a list of the form (TITLE ITEM1 ITEM2...). -Each ITEM is a cons cell (STRING . VALUE). -The return value is VALUE from the chosen item. - -An ITEM may also be just a string--that makes a nonselectable item. -An ITEM may also be nil--that means to put all preceding items -on the left of the dialog box and all following items on the right. -\(By default, approximately half appear on each side.) - -If HEADER is non-nil, the frame title for the box is "Information", -otherwise it is "Question". */) - (Lisp_Object position, Lisp_Object contents, Lisp_Object header) +#ifdef HAVE_DIALOGS +Lisp_Object +w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) { - struct frame *f = NULL; - Lisp_Object window; - - /* Decode the first argument: find the window or frame to use. */ - if (EQ (position, Qt) - || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) - { -#if 0 /* Using the frame the mouse is on may not be right. */ - /* Use the mouse's current position. */ - struct frame *new_f = SELECTED_FRAME (); - Lisp_Object bar_window; - enum scroll_bar_part part; - Time time; - Lisp_Object x, y; - - (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); - - if (new_f != 0) - XSETFRAME (window, new_f); - else - window = selected_window; -#endif - window = selected_window; - } - else if (CONSP (position)) - { - Lisp_Object tem = XCAR (position); - if (CONSP (tem)) - window = Fcar (XCDR (position)); - else - { - tem = Fcar (XCDR (position)); /* EVENT_START (position) */ - window = Fcar (tem); /* POSN_WINDOW (tem) */ - } - } - else if (WINDOWP (position) || FRAMEP (position)) - window = position; - else - window = Qnil; - - /* Decode where to put the menu. */ - - if (FRAMEP (window)) - f = XFRAME (window); - else if (WINDOWP (window)) - { - CHECK_LIVE_WINDOW (window); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - } - else - /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, - but I don't want to make one now. */ - CHECK_WINDOW (window); + Lisp_Object title; + char *error_name; + Lisp_Object selection; check_window_system (f); -#ifndef HAVE_DIALOGS - - { - /* Handle simple Yes/No choices as MessageBox popups. */ - if (is_simple_dialog (contents)) - return simple_dialog_show (f, contents, header); - else - { - /* Display a menu with these alternatives - in the middle of frame F. */ - Lisp_Object x, y, frame, newpos; - XSETFRAME (frame, f); - XSETINT (x, FRAME_PIXEL_WIDTH (f) / 2); - XSETINT (y, FRAME_PIXEL_HEIGHT (f) / 2); - newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil)); - return Fx_popup_menu (newpos, - Fcons (Fcar (contents), Fcons (contents, Qnil))); - } - } -#else /* HAVE_DIALOGS */ - { - Lisp_Object title; - char *error_name; - Lisp_Object selection; - - /* Decode the dialog items from what was specified. */ - title = Fcar (contents); - CHECK_STRING (title); + /* Decode the dialog items from what was specified. */ + title = Fcar (contents); + CHECK_STRING (title); - list_of_panes (Fcons (contents, Qnil)); + list_of_panes (Fcons (contents, Qnil)); - /* Display them in a dialog box. */ - block_input (); - selection = w32_dialog_show (f, 0, title, header, &error_name); - unblock_input (); + /* Display them in a dialog box. */ + block_input (); + selection = w32_dialog_show (f, 0, title, header, &error_name); + unblock_input (); - discard_menu_items (); - FRAME_DISPLAY_INFO (f)->grabbed = 0; + discard_menu_items (); + FRAME_DISPLAY_INFO (f)->grabbed = 0; - if (error_name) error (error_name); - return selection; - } -#endif /* HAVE_DIALOGS */ + if (error_name) error (error_name); + return selection; } +#endif /* HAVE_DIALOGS */ /* Activate the menu bar of frame F. This is called from keyboard.c when it gets the @@ -1724,9 +1629,6 @@ syms_of_w32menu (void) DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); defsubr (&Smenu_or_popup_active_p); -#ifdef HAVE_MENUS - defsubr (&Sx_popup_dialog); -#endif } /* diff --git a/src/w32term.h b/src/w32term.h index 095ca54e3e8..8244487dfc7 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -798,6 +798,10 @@ typedef char guichar_t; #define GUI_SDATA(x) ((guichar_t*) SDATA (x)) +#if defined HAVE_DIALOGS +extern Lisp_Object w32_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); +#endif + extern void syms_of_w32term (void); extern void syms_of_w32menu (void); extern void syms_of_w32fns (void); diff --git a/src/xmenu.c b/src/xmenu.c index 054a52e7760..fe0e229ef20 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -192,149 +192,6 @@ mouse_position_for_popup (struct frame *f, int *x, int *y) #endif /* HAVE_X_WINDOWS */ -#ifdef HAVE_MENUS - -DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, - doc: /* Pop up a dialog box and return user's selection. -POSITION specifies which frame to use. -This is normally a mouse button event or a window or frame. -If POSITION is t, it means to use the frame the mouse is on. -The dialog box appears in the middle of the specified frame. - -CONTENTS specifies the alternatives to display in the dialog box. -It is a list of the form (DIALOG ITEM1 ITEM2...). -Each ITEM is a cons cell (STRING . VALUE). -The return value is VALUE from the chosen item. - -An ITEM may also be just a string--that makes a nonselectable item. -An ITEM may also be nil--that means to put all preceding items -on the left of the dialog box and all following items on the right. -\(By default, approximately half appear on each side.) - -If HEADER is non-nil, the frame title for the box is "Information", -otherwise it is "Question". - -If the user gets rid of the dialog box without making a valid choice, -for instance using the window manager, then this produces a quit and -`x-popup-dialog' does not return. */) - (Lisp_Object position, Lisp_Object contents, Lisp_Object header) -{ - struct frame *f = NULL; - Lisp_Object window; - - /* Decode the first argument: find the window or frame to use. */ - if (EQ (position, Qt) - || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) - { -#if 0 /* Using the frame the mouse is on may not be right. */ - /* Use the mouse's current position. */ - struct frame *new_f = SELECTED_FRAME (); - Lisp_Object bar_window; - enum scroll_bar_part part; - Time time; - Lisp_Object x, y; - - (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time); - - if (new_f != 0) - XSETFRAME (window, new_f); - else - window = selected_window; -#endif - window = selected_window; - } - else if (CONSP (position)) - { - Lisp_Object tem = XCAR (position); - if (CONSP (tem)) - window = Fcar (XCDR (position)); - else - { - tem = Fcar (XCDR (position)); /* EVENT_START (position) */ - window = Fcar (tem); /* POSN_WINDOW (tem) */ - } - } - else if (WINDOWP (position) || FRAMEP (position)) - window = position; - else - window = Qnil; - - /* Decode where to put the menu. */ - - if (FRAMEP (window)) - f = XFRAME (window); - else if (WINDOWP (window)) - { - CHECK_LIVE_WINDOW (window); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - } - else - /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, - but I don't want to make one now. */ - CHECK_WINDOW (window); - - check_window_system (f); - - /* Force a redisplay before showing the dialog. If a frame is created - just before showing the dialog, its contents may not have been fully - drawn, as this depends on timing of events from the X server. Redisplay - is not done when a dialog is shown. If redisplay could be done in the - X event loop (i.e. the X event loop does not run in a signal handler) - this would not be needed. - - Do this before creating the widget value that points to Lisp - string contents, because Fredisplay may GC and relocate them. */ - Fredisplay (Qt); - -#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) - /* Display a menu with these alternatives - in the middle of frame F. */ - { - Lisp_Object x, y, frame, newpos; - XSETFRAME (frame, f); - XSETINT (x, FRAME_PIXEL_WIDTH (f) / 2); - XSETINT (y, FRAME_PIXEL_HEIGHT (f) / 2); - newpos = list2 (list2 (x, y), frame); - - return Fx_popup_menu (newpos, - list2 (Fcar (contents), contents)); - } -#else - { - Lisp_Object title; - const char *error_name; - Lisp_Object selection; - ptrdiff_t specpdl_count = SPECPDL_INDEX (); - - /* Decode the dialog items from what was specified. */ - title = Fcar (contents); - CHECK_STRING (title); - record_unwind_protect_void (unuse_menu_items); - - if (NILP (Fcar (Fcdr (contents)))) - /* No buttons specified, add an "Ok" button so users can pop down - the dialog. Also, the lesstif/motif version crashes if there are - no buttons. */ - contents = list2 (title, Fcons (build_string ("Ok"), Qt)); - - list_of_panes (list1 (contents)); - - /* Display them in a dialog box. */ - block_input (); - selection = xdialog_show (f, 0, title, header, &error_name); - unblock_input (); - - unbind_to (specpdl_count, Qnil); - discard_menu_items (); - - if (error_name) error ("%s", error_name); - return selection; - } -#endif -} - - #ifndef MSDOS #if defined USE_GTK || defined USE_MOTIF @@ -2170,6 +2027,41 @@ xdialog_show (struct frame *f, return Qnil; } +Lisp_Object +xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) +{ + Lisp_Object title; + const char *error_name; + Lisp_Object selection; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + + check_window_system (f); + + /* Decode the dialog items from what was specified. */ + title = Fcar (contents); + CHECK_STRING (title); + record_unwind_protect_void (unuse_menu_items); + + if (NILP (Fcar (Fcdr (contents)))) + /* No buttons specified, add an "Ok" button so users can pop down + the dialog. Also, the lesstif/motif version crashes if there are + no buttons. */ + contents = list2 (title, Fcons (build_string ("Ok"), Qt)); + + list_of_panes (list1 (contents)); + + /* Display them in a dialog box. */ + block_input (); + selection = xdialog_show (f, 0, title, header, &error_name); + unblock_input (); + + unbind_to (specpdl_count, Qnil); + discard_menu_items (); + + if (error_name) error ("%s", error_name); + return selection; +} + #else /* not USE_X_TOOLKIT && not USE_GTK */ /* The frame of the last activated non-toolkit menu bar. @@ -2531,8 +2423,6 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps, #endif /* not USE_X_TOOLKIT */ -#endif /* HAVE_MENUS */ - #ifndef MSDOS /* Detect if a dialog or menu has been posted. MSDOS has its own implementation on msdos.c. */ @@ -2574,8 +2464,4 @@ syms_of_xmenu (void) Ffset (intern_c_string ("accelerate-menu"), intern_c_string (Sx_menu_bar_open_internal.symbol_name)); #endif - -#ifdef HAVE_MENUS - defsubr (&Sx_popup_dialog); -#endif } diff --git a/src/xterm.h b/src/xterm.h index 36aa8e52b1c..5ec4851a0e1 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1035,6 +1035,10 @@ extern void x_free_dpy_colors (Display *, Screen *, Colormap, /* Defined in xmenu.c */ +#if defined USE_X_TOOLKIT || defined USE_GTK +extern Lisp_Object xw_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); +#endif + #if defined USE_GTK || defined USE_MOTIF extern void x_menu_set_in_use (int); #endif