comparison src/xterm.c @ 105693:964ff7cbc8a6

Fix resize due to font change on a maximized/xmonad-controlled frame. * xterm.h (x_wait_for_event): Declare it. * xterm.c (pending_event_wait): New variable. (handle_one_xevent): Set pending_event_wait.eventtype to 0 if we see pending_event_wait.eventtype. (handle_one_xevent): Don't change gravity when parent changes. (x_new_font): Call change_frame_size with new rows/columns before we try to resize the frame. (x_wait_for_event): New function. (x_set_window_size_1): Don't change gravity unless change_gravity is set. Call XResizeWindow with FRAME_OUTER_WINDOW. If we are visible, don't change frame size, instead wait for the ConfigureNotify. (x_set_window_size): Call x_set_window_size_1 for USE_X_TOOLKIT also. (x_wm_set_size_hint): Remove ifdefs for USE_X_TOOLKIT. (x_initialize): Initialize pending_event_wait. * xmenu.c (set_frame_menubar): Add internal border width to menu bar size. * widget.c (EmacsFrameSetValues): Add comment. (EmacsFrameSetCharSize): Just call x_set_window_size. * gtkutil.c (xg_frame_set_char_size): Flush events and call x_wait_for_event. (flush_and_sync): Removed again. (xg_get_font_name): Suggest monospace if no previous font is known.
author Jan Djärv <jan.h.d@swipnet.se>
date Wed, 21 Oct 2009 18:29:46 +0000
parents 061e00486e48
children 56d1856a3ea9
comparison
equal deleted inserted replaced
105692:15b4b661ceb1 105693:964ff7cbc8a6
84 #include "process.h" 84 #include "process.h"
85 #include "atimer.h" 85 #include "atimer.h"
86 #include "keymap.h" 86 #include "keymap.h"
87 #include "font.h" 87 #include "font.h"
88 #include "fontset.h" 88 #include "fontset.h"
89 #include "sysselect.h"
89 90
90 #ifdef USE_X_TOOLKIT 91 #ifdef USE_X_TOOLKIT
91 #include <X11/Shell.h> 92 #include <X11/Shell.h>
92 #endif 93 #endif
93 94
197 198
198 extern struct frame *updating_frame; 199 extern struct frame *updating_frame;
199 200
200 /* This is a frame waiting to be auto-raised, within XTread_socket. */ 201 /* This is a frame waiting to be auto-raised, within XTread_socket. */
201 202
202 struct frame *pending_autoraise_frame; 203 static struct frame *pending_autoraise_frame;
204
205 /* This is a frame waiting for an event matching mask, within XTread_socket. */
206
207 static struct {
208 struct frame *f;
209 int eventtype;
210 } pending_event_wait;
203 211
204 #ifdef USE_X_TOOLKIT 212 #ifdef USE_X_TOOLKIT
205 /* The application context for Xt use. */ 213 /* The application context for Xt use. */
206 XtAppContext Xt_app_con; 214 XtAppContext Xt_app_con;
207 static String Xt_default_resources[] = {0}; 215 static String Xt_default_resources[] = {0};
5831 *finish = X_EVENT_NORMAL; 5839 *finish = X_EVENT_NORMAL;
5832 5840
5833 EVENT_INIT (inev.ie); 5841 EVENT_INIT (inev.ie);
5834 inev.ie.kind = NO_EVENT; 5842 inev.ie.kind = NO_EVENT;
5835 inev.ie.arg = Qnil; 5843 inev.ie.arg = Qnil;
5836 5844
5845 if (pending_event_wait.eventtype == event.type)
5846 pending_event_wait.eventtype = 0; /* Indicates we got it. */
5847
5837 switch (event.type) 5848 switch (event.type)
5838 { 5849 {
5839 case ClientMessage: 5850 case ClientMessage:
5840 { 5851 {
5841 if (event.xclient.message_type 5852 if (event.xclient.message_type
6777 #endif /* not USE_GTK */ 6788 #endif /* not USE_GTK */
6778 #endif 6789 #endif
6779 6790
6780 #ifdef USE_GTK 6791 #ifdef USE_GTK
6781 /* GTK creates windows but doesn't map them. 6792 /* GTK creates windows but doesn't map them.
6782 Only get real positions and check fullscreen when mapped. */ 6793 Only get real positions when mapped. */
6783 if (FRAME_GTK_OUTER_WIDGET (f) 6794 if (FRAME_GTK_OUTER_WIDGET (f)
6784 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f))) 6795 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
6785 #endif 6796 #endif
6786 { 6797 {
6787 x_real_positions (f, &f->left_pos, &f->top_pos); 6798 x_real_positions (f, &f->left_pos, &f->top_pos);
6790 #ifdef HAVE_X_I18N 6801 #ifdef HAVE_X_I18N
6791 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea)) 6802 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6792 xic_set_statusarea (f); 6803 xic_set_statusarea (f);
6793 #endif 6804 #endif
6794 6805
6795 #ifndef USE_GTK
6796 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6797 {
6798 /* Since the WM decorations come below top_pos now,
6799 we must put them below top_pos in the future. */
6800 f->win_gravity = NorthWestGravity;
6801 x_wm_set_size_hint (f, (long) 0, 0);
6802 }
6803 #endif
6804 } 6806 }
6805 goto OTHER; 6807 goto OTHER;
6806 6808
6807 case ButtonRelease: 6809 case ButtonRelease:
6808 case ButtonPress: 6810 case ButtonPress:
8041 In that case, the right thing to do is extend rows/cols to 8043 In that case, the right thing to do is extend rows/cols to
8042 the current frame size. We do that first if x_set_window_size 8044 the current frame size. We do that first if x_set_window_size
8043 turns out to not be a no-op (there is no way to know). 8045 turns out to not be a no-op (there is no way to know).
8044 The size will be adjusted again if the frame gets a 8046 The size will be adjusted again if the frame gets a
8045 ConfigureNotify event as a result of x_set_window_size. */ 8047 ConfigureNotify event as a result of x_set_window_size. */
8046 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, 8048 int pixelh = FRAME_PIXEL_HEIGHT (f);
8047 FRAME_PIXEL_HEIGHT (f)); 8049 #ifdef USE_X_TOOLKIT
8050 /* The menu bar is not part of text lines. The tool bar
8051 is however. */
8052 pixelh -= FRAME_MENUBAR_HEIGHT (f);
8053 #endif
8054 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
8048 int cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f)); 8055 int cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
8056
8049 change_frame_size (f, rows, cols, 0, 1, 0); 8057 change_frame_size (f, rows, cols, 0, 1, 0);
8050 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); 8058 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
8051 } 8059 }
8052 } 8060 }
8053 8061
8808 8816
8809 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0); 8817 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8810 } 8818 }
8811 8819
8812 8820
8821 /* Wait for an event on frame F matching EVENTTYPE. */
8822 void
8823 x_wait_for_event (f, eventtype)
8824 struct frame *f;
8825 int eventtype;
8826 {
8827 int level = interrupt_input_blocked;
8828
8829 SELECT_TYPE fds;
8830 EMACS_TIME tmo, tmo_at, time_now;
8831 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
8832
8833 pending_event_wait.f = f;
8834 pending_event_wait.eventtype = eventtype;
8835
8836 /* Set timeout to 0.1 second. Hopefully not noticable.
8837 Maybe it should be configurable. */
8838 EMACS_SET_SECS_USECS (tmo, 0, 100000);
8839 EMACS_GET_TIME (tmo_at);
8840 EMACS_ADD_TIME (tmo_at, tmo_at, tmo);
8841
8842 while (pending_event_wait.eventtype)
8843 {
8844 interrupt_input_pending = 1;
8845 TOTALLY_UNBLOCK_INPUT;
8846 /* XTread_socket is called after unblock. */
8847 BLOCK_INPUT;
8848 interrupt_input_blocked = level;
8849
8850 FD_ZERO (&fds);
8851 FD_SET (fd, &fds);
8852
8853 EMACS_GET_TIME (time_now);
8854 EMACS_SUB_TIME (tmo, tmo_at, time_now);
8855
8856 if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
8857 break; /* Timeout */
8858 }
8859 pending_event_wait.f = 0;
8860 pending_event_wait.eventtype = 0;
8861 }
8862
8863
8813 /* Change the size of frame F's X window to COLS/ROWS in the case F 8864 /* Change the size of frame F's X window to COLS/ROWS in the case F
8814 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to 8865 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8815 top-left-corner window gravity for this size change and subsequent 8866 top-left-corner window gravity for this size change and subsequent
8816 size changes. Otherwise we leave the window gravity unchanged. */ 8867 size changes. Otherwise we leave the window gravity unchanged. */
8817 8868
8831 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) 8882 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
8832 : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))); 8883 : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)));
8833 8884
8834 compute_fringe_widths (f, 0); 8885 compute_fringe_widths (f, 0);
8835 8886
8836 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols); 8887 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
8837 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); 8888 + 2*f->border_width;
8838 8889 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
8839 f->win_gravity = NorthWestGravity; 8890 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)
8891 + 2*f->border_width;
8892
8893 if (change_gravity) f->win_gravity = NorthWestGravity;
8840 x_wm_set_size_hint (f, (long) 0, 0); 8894 x_wm_set_size_hint (f, (long) 0, 0);
8841 8895 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8842 XSync (FRAME_X_DISPLAY (f), False);
8843 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8844 pixelwidth, pixelheight); 8896 pixelwidth, pixelheight);
8897
8898
8899 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8900 receive in the ConfigureNotify event; if we get what we asked
8901 for, then the event won't cause the screen to become garbaged, so
8902 we have to make sure to do it here. */
8903 SET_FRAME_GARBAGED (f);
8845 8904
8846 /* Now, strictly speaking, we can't be sure that this is accurate, 8905 /* Now, strictly speaking, we can't be sure that this is accurate,
8847 but the window manager will get around to dealing with the size 8906 but the window manager will get around to dealing with the size
8848 change request eventually, and we'll hear how it went when the 8907 change request eventually, and we'll hear how it went when the
8849 ConfigureNotify event gets here. 8908 ConfigureNotify event gets here.
8854 wouldn't be reported in the frame parameters until some random 8913 wouldn't be reported in the frame parameters until some random
8855 point in the future when the ConfigureNotify event arrives. 8914 point in the future when the ConfigureNotify event arrives.
8856 8915
8857 We pass 1 for DELAY since we can't run Lisp code inside of 8916 We pass 1 for DELAY since we can't run Lisp code inside of
8858 a BLOCK_INPUT. */ 8917 a BLOCK_INPUT. */
8859 change_frame_size (f, rows, cols, 0, 1, 0); 8918
8860 FRAME_PIXEL_WIDTH (f) = pixelwidth; 8919 /* But the ConfigureNotify may in fact never arrive, and then this is
8861 FRAME_PIXEL_HEIGHT (f) = pixelheight; 8920 not right if the frame is visible. Instead wait (with timeout)
8862 8921 for the ConfigureNotify. */
8863 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to 8922 if (f->async_visible)
8864 receive in the ConfigureNotify event; if we get what we asked 8923 x_wait_for_event (f, ConfigureNotify);
8865 for, then the event won't cause the screen to become garbaged, so 8924 else
8866 we have to make sure to do it here. */ 8925 {
8867 SET_FRAME_GARBAGED (f); 8926 change_frame_size (f, rows, cols, 0, 1, 0);
8868 8927 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8869 XFlush (FRAME_X_DISPLAY (f)); 8928 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8929 x_sync (f);
8930 }
8870 } 8931 }
8871 8932
8872 8933
8873 /* Call this to change the size of frame F's x-window. 8934 /* Call this to change the size of frame F's x-window.
8874 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity 8935 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8886 #ifdef USE_GTK 8947 #ifdef USE_GTK
8887 if (FRAME_GTK_WIDGET (f)) 8948 if (FRAME_GTK_WIDGET (f))
8888 xg_frame_set_char_size (f, cols, rows); 8949 xg_frame_set_char_size (f, cols, rows);
8889 else 8950 else
8890 x_set_window_size_1 (f, change_gravity, cols, rows); 8951 x_set_window_size_1 (f, change_gravity, cols, rows);
8891 #elif USE_X_TOOLKIT 8952 #else /* not USE_GTK */
8892
8893 if (f->output_data.x->widget != NULL)
8894 {
8895 /* The x and y position of the widget is clobbered by the
8896 call to XtSetValues within EmacsFrameSetCharSize.
8897 This is a real kludge, but I don't understand Xt so I can't
8898 figure out a correct fix. Can anyone else tell me? -- rms. */
8899 int xpos = f->output_data.x->widget->core.x;
8900 int ypos = f->output_data.x->widget->core.y;
8901 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
8902 f->output_data.x->widget->core.x = xpos;
8903 f->output_data.x->widget->core.y = ypos;
8904 }
8905 else
8906 x_set_window_size_1 (f, change_gravity, cols, rows);
8907
8908 #else /* not USE_X_TOOLKIT */
8909 8953
8910 x_set_window_size_1 (f, change_gravity, cols, rows); 8954 x_set_window_size_1 (f, change_gravity, cols, rows);
8911 8955
8912 #endif /* not USE_X_TOOLKIT */ 8956 #endif /* not USE_GTK */
8913 8957
8914 /* If cursor was outside the new size, mark it as off. */ 8958 /* If cursor was outside the new size, mark it as off. */
8915 mark_window_cursors_off (XWINDOW (f->root_window)); 8959 mark_window_cursors_off (XWINDOW (f->root_window));
8916 8960
8917 /* Clear out any recollection of where the mouse highlighting was, 8961 /* Clear out any recollection of where the mouse highlighting was,
9609 struct frame *f; 9653 struct frame *f;
9610 long flags; 9654 long flags;
9611 int user_position; 9655 int user_position;
9612 { 9656 {
9613 XSizeHints size_hints; 9657 XSizeHints size_hints;
9614
9615 #ifdef USE_X_TOOLKIT
9616 Arg al[2];
9617 int ac = 0;
9618 Dimension widget_width, widget_height;
9619 #endif
9620
9621 Window window = FRAME_OUTER_WINDOW (f); 9658 Window window = FRAME_OUTER_WINDOW (f);
9622 9659
9623 /* Setting PMaxSize caused various problems. */ 9660 /* Setting PMaxSize caused various problems. */
9624 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */; 9661 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9625 9662
9626 size_hints.x = f->left_pos; 9663 size_hints.x = f->left_pos;
9627 size_hints.y = f->top_pos; 9664 size_hints.y = f->top_pos;
9628 9665
9629 #ifdef USE_X_TOOLKIT
9630 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
9631 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
9632 XtGetValues (f->output_data.x->widget, al, ac);
9633 size_hints.height = widget_height;
9634 size_hints.width = widget_width;
9635 #else /* not USE_X_TOOLKIT */
9636 size_hints.height = FRAME_PIXEL_HEIGHT (f); 9666 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9637 size_hints.width = FRAME_PIXEL_WIDTH (f); 9667 size_hints.width = FRAME_PIXEL_WIDTH (f);
9638 #endif /* not USE_X_TOOLKIT */
9639 9668
9640 size_hints.width_inc = FRAME_COLUMN_WIDTH (f); 9669 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9641 size_hints.height_inc = FRAME_LINE_HEIGHT (f); 9670 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9642 size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)) 9671 size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
9643 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); 9672 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9644 size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)) 9673 size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
9645 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); 9674 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9646 9675
9647 /* Calculate the base and minimum sizes. 9676 /* Calculate the base and minimum sizes. */
9648
9649 (When we use the X toolkit, we don't do it here.
9650 Instead we copy the values that the widgets are using, below.) */
9651 #ifndef USE_X_TOOLKIT
9652 { 9677 {
9653 int base_width, base_height; 9678 int base_width, base_height;
9654 int min_rows = 0, min_cols = 0; 9679 int min_rows = 0, min_cols = 0;
9655 9680
9656 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); 9681 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9668 them; otherwise, we set the min_width and min_height members 9693 them; otherwise, we set the min_width and min_height members
9669 to the size for a zero x zero frame. */ 9694 to the size for a zero x zero frame. */
9670 9695
9671 size_hints.flags |= PBaseSize; 9696 size_hints.flags |= PBaseSize;
9672 size_hints.base_width = base_width; 9697 size_hints.base_width = base_width;
9673 size_hints.base_height = base_height; 9698 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
9674 size_hints.min_width = base_width + min_cols * size_hints.width_inc; 9699 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9675 size_hints.min_height = base_height + min_rows * size_hints.height_inc; 9700 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9676 } 9701 }
9677 9702
9678 /* If we don't need the old flags, we don't need the old hint at all. */ 9703 /* If we don't need the old flags, we don't need the old hint at all. */
9679 if (flags) 9704 if (flags)
9680 { 9705 {
9681 size_hints.flags |= flags; 9706 size_hints.flags |= flags;
9682 goto no_read; 9707 goto no_read;
9683 } 9708 }
9684 #endif /* not USE_X_TOOLKIT */
9685 9709
9686 { 9710 {
9687 XSizeHints hints; /* Sometimes I hate X Windows... */ 9711 XSizeHints hints; /* Sometimes I hate X Windows... */
9688 long supplied_return; 9712 long supplied_return;
9689 int value; 9713 int value;
9690 9714
9691 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints, 9715 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9692 &supplied_return); 9716 &supplied_return);
9693
9694 #ifdef USE_X_TOOLKIT
9695 size_hints.base_height = hints.base_height;
9696 size_hints.base_width = hints.base_width;
9697 size_hints.min_height = hints.min_height;
9698 size_hints.min_width = hints.min_width;
9699 #endif
9700 9717
9701 if (flags) 9718 if (flags)
9702 size_hints.flags |= flags; 9719 size_hints.flags |= flags;
9703 else 9720 else
9704 { 9721 {
9713 if (hints.flags & USSize) 9730 if (hints.flags & USSize)
9714 size_hints.flags |= USSize; 9731 size_hints.flags |= USSize;
9715 } 9732 }
9716 } 9733 }
9717 9734
9718 #ifndef USE_X_TOOLKIT
9719 no_read: 9735 no_read:
9720 #endif
9721 9736
9722 #ifdef PWinGravity 9737 #ifdef PWinGravity
9723 size_hints.win_gravity = f->win_gravity; 9738 size_hints.win_gravity = f->win_gravity;
9724 size_hints.flags |= PWinGravity; 9739 size_hints.flags |= PWinGravity;
9725 9740
10789 xaw3d_arrow_scroll = False; 10804 xaw3d_arrow_scroll = False;
10790 xaw3d_pick_top = True; 10805 xaw3d_pick_top = True;
10791 #endif 10806 #endif
10792 #endif 10807 #endif
10793 10808
10809 pending_autoraise_frame = 0;
10810 pending_event_wait.f = 0;
10811 pending_event_wait.eventtype = 0;
10812
10794 /* Note that there is no real way portable across R3/R4 to get the 10813 /* Note that there is no real way portable across R3/R4 to get the
10795 original error handler. */ 10814 original error handler. */
10796 XSetErrorHandler (x_error_handler); 10815 XSetErrorHandler (x_error_handler);
10797 XSetIOErrorHandler (x_io_error_quitter); 10816 XSetIOErrorHandler (x_io_error_quitter);
10798 10817