/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
/* Default to using XIM if available. */
#ifdef USE_XIM
-int use_xim = 1;
+bool use_xim = true;
#else
-int use_xim = 0; /* configure --without-xim */
+bool use_xim = false; /* configure --without-xim */
#endif
/* Non-zero means that a HELP_EVENT has been generated since Emacs
static Time ignore_next_mouse_click_timeout;
-/* Incremented by XTread_socket whenever it really tries to read
- events. */
-
-static int volatile input_signal_count;
-
/* Used locally within XTread_socket. */
static int x_noop_count;
static int handle_one_xevent (struct x_display_info *,
const XEvent *, int *,
struct input_event *);
-#ifdef USE_GTK
+#if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
static int x_dispatch_event (XEvent *, Display *);
#endif
/* Don't declare this _Noreturn because we want no
x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct face *face;
-
- face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
- if (face)
- XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- face->foreground);
+ struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+ struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+ struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+ unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+ unsigned long color_first = (face_first
+ ? face_first->foreground
+ : FRAME_FOREGROUND_PIXEL (f));
+ unsigned long color_last = (face_last
+ ? face_last->foreground
+ : FRAME_FOREGROUND_PIXEL (f));
+ Display *display = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->normal_gc, x0, y0, x1 - x0, y1 - y0);
+ if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+ /* Vertical. */
+ {
+ XSetForeground (display, f->output_data.x->normal_gc, color_first);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0, y0, 1, y1 - y0);
+ XSetForeground (display, f->output_data.x->normal_gc, color);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+ XSetForeground (display, f->output_data.x->normal_gc, color_last);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x1 - 1, y0, 1, y1 - y0);
+ }
+ else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+ /* Horizontal. */
+ {
+ XSetForeground (display, f->output_data.x->normal_gc, color_first);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0, y0, x1 - x0, 1);
+ XSetForeground (display, f->output_data.x->normal_gc, color);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+ XSetForeground (display, f->output_data.x->normal_gc, color_last);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0, y1 - 1, x1 - x0, 1);
+ }
+ else
+ {
+ XSetForeground (display, f->output_data.x->normal_gc, color);
+ XFillRectangle (display, window, f->output_data.x->normal_gc,
+ x0, y0, x1 - x0, y1 - y0);
+ }
}
/* End update of window W.
}
+/* Clear under internal border if any for non-toolkit builds. */
+
+
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
+void
+x_clear_under_internal_border (struct frame *f)
+{
+ if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
+ {
+ Display *display = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
+ int border = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = FRAME_PIXEL_WIDTH (f);
+ int height = FRAME_PIXEL_HEIGHT (f);
+ int margin = FRAME_TOP_MARGIN_HEIGHT (f);
+
+ block_input ();
+ x_clear_area (display, window, 0, 0, border, height);
+ x_clear_area (display, window, 0, margin, width, border);
+ x_clear_area (display, window, width - border, 0, border, height);
+ x_clear_area (display, window, 0, height - border, width, border);
+ unblock_input ();
+ }
+}
+#endif
+
/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
arrow bitmaps, or clear the fringes if no bitmaps are required
before DESIRED_ROW is made current. This function is called from
static void
x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
{
- struct frame *f;
- int width, height;
-
eassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
desired_row->redraw_fringe_bitmaps_p = 1;
+#ifdef USE_X_TOOLKIT
/* When a window has disappeared, make sure that no rest of
full-width rows stays visible in the internal border. Could
check here if updated window is the leftmost/rightmost window,
but I guess it's not worth doing since vertically split windows
are almost never used, internal border is rarely set, and the
overhead is very small. */
- if (windows_or_buffers_changed
- && desired_row->full_width_p
- && (f = XFRAME (w->frame),
- width = FRAME_INTERNAL_BORDER_WIDTH (f),
- width != 0)
- && (height = desired_row->visible_height,
- height > 0))
- {
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+ {
+ struct frame *f;
+ int width, height;
+
+ if (windows_or_buffers_changed
+ && desired_row->full_width_p
+ && (f = XFRAME (w->frame),
+ width = FRAME_INTERNAL_BORDER_WIDTH (f),
+ width != 0)
+ && (height = desired_row->visible_height,
+ height > 0))
+ {
+ int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
- block_input ();
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height);
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_PIXEL_WIDTH (f) - width,
- y, width, height);
- unblock_input ();
- }
+ block_input ();
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_PIXEL_WIDTH (f) - width,
+ y, width, height);
+ unblock_input ();
+ }
+ }
+#endif
}
static void
#endif
{
/* Get the height not including a menu bar widget. */
- int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+ int height = FRAME_PIXEL_HEIGHT (f);
/* Height of each line to flash. */
int flash_height = FRAME_LINE_HEIGHT (f);
/* These will be the left and right margins of the rectangles. */
/* Don't stop displaying the initial startup message
for a switch-frame event we don't need. */
/* When run as a daemon, Vterminal_frame is always NIL. */
- bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt))
+ bufp->arg = (((NILP (Vterminal_frame)
+ || ! FRAME_X_P (XFRAME (Vterminal_frame))
+ || EQ (Fdaemonp (), Qt))
&& CONSP (Vframe_list)
&& !NILP (XCDR (Vframe_list)))
? Qt : Qnil);
/* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
- width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+ width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
#ifdef USE_GTK
/* Don't pass keys to GTK. A Tab will shift focus to the
tool bar in GTK 2.4. Keys will still go to menus and
- dialogs because in that case popup_activated is TRUE
+ dialogs because in that case popup_activated is nonzero
(see above). */
*finish = X_EVENT_DROP;
#endif
|| event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
{
change_frame_size (f, width, height, 0, 1, 0, 1);
- SET_FRAME_GARBAGED (f);
+ x_clear_under_internal_border (f);
+ SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
- FRAME_PIXEL_WIDTH (f) = event->xconfigure.width;
- FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height;
+/** FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; **/
+/** FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; **/
#endif /* not USE_GTK */
#endif
return count;
}
-#if defined USE_GTK || defined USE_X_TOOLKIT
-
/* Handles the XEvent EVENT on display DISPLAY.
This is used for event loops outside the normal event handling,
i.e. looping while a popup menu or a dialog is posted.
return finish;
}
-#endif
-
/* Read events coming from the X server.
Return as soon as there are no more events to be read.
block_input ();
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
/* For debugging, this gives a way to fake an I/O error. */
if (dpyinfo == XTread_socket_fake_io_error)
{
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
+ int unit;
if (fontset < 0)
fontset = fontset_from_font (font_object);
FRAME_COLUMN_WIDTH (f) = font->average_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
- compute_fringe_widths (f, 1);
-
- /* Compute the scroll bar width in character columns. */
- if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
- {
- int wid = FRAME_COLUMN_WIDTH (f);
+ FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+ FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f)
- = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
- }
- else
- {
- int wid = FRAME_COLUMN_WIDTH (f);
+ compute_fringe_widths (f, 1);
- FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 14;
- FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
- }
+ unit = FRAME_COLUMN_WIDTH (f);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ /* The width of a toolkit scrollbar does not change with the new
+ font but we have to calculate the number of columns it occupies
+ anew. */
+ FRAME_CONFIG_SCROLL_BAR_COLS (f)
+ = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
+#else
+ /* The width of a non-toolkit scrollbar is at least 14 pixels and a
+ multiple of the frame's character width. */
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
+ = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
+#endif
if (FRAME_X_WINDOW (f) != 0)
{
doing it because it's done in Fx_show_tip, and it leads to
problems because the tip frame has no widget. */
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
- x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+ x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
}
#ifdef HAVE_X_I18N
int pixelwidth, pixelheight;
check_frame_size (f, &width, &height, pixelwise);
- f->scroll_bar_actual_width
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
compute_fringe_widths (f, 0);
- pixelwidth =
- (pixelwise ? width : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
- + FRAME_TOOLBAR_WIDTH (f);
- pixelheight =
- (pixelwise ? height : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
- + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
-
+ pixelwidth = ((pixelwise
+ ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
+ : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
+ + FRAME_TOOLBAR_WIDTH (f));
+ pixelheight = ((pixelwise
+ ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
+ : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
+ + FRAME_MENUBAR_HEIGHT (f)
+ + FRAME_TOOLBAR_HEIGHT (f));
if (change_gravity) f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
else
{
change_frame_size (f, width, height, 0, 1, 0, 1);
- FRAME_PIXEL_WIDTH (f) = pixelwidth;
- FRAME_PIXEL_HEIGHT (f) = pixelheight;
x_sync (f);
}
}
{
block_input ();
+ check_frame_size (f, &width, &height, pixelwise);
+
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
int text_width, text_height;
#endif
text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
- /* Update f->scroll_bar_actual_width because it is used in
- FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
- f->scroll_bar_actual_width
- = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
+
change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
}
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
- xg_frame_set_char_size (f, width, height);
+ if (! pixelwise)
+ xg_frame_set_char_size (f, width * FRAME_COLUMN_WIDTH (f),
+ height * FRAME_LINE_HEIGHT (f));
+ else
+ xg_frame_set_char_size (f, width, height);
else
x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
#else /* not USE_GTK */
x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+#if !defined USE_X_TOOLKIT
+ x_clear_under_internal_border (f);
+#endif
#endif /* not USE_GTK */
x_make_frame_visible (struct frame *f)
{
int original_top, original_left;
- int retry_count = 2;
-
- retry:
block_input ();
so that incoming events are handled. */
{
Lisp_Object frame;
- int count;
/* This must be before UNBLOCK_INPUT
since events that arrive in response to the actions above
will set it when they are handled. */
XSETFRAME (frame, f);
- /* Wait until the frame is visible. Process X events until a
- MapNotify event has been seen, or until we think we won't get a
- MapNotify at all.. */
- for (count = input_signal_count + 10;
- input_signal_count < count && !FRAME_VISIBLE_P (f);)
+ /* Process X events until a MapNotify event has been seen. */
+ while (!FRAME_VISIBLE_P (f))
{
/* Force processing of queued events. */
x_sync (f);
- /* Machines that do polling rather than SIGIO have been
+ /* This hack is still in use at least for Cygwin. See
+ http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html.
+
+ Machines that do polling rather than SIGIO have been
observed to go into a busy-wait here. So we'll fake an
alarm signal to let the handler know that there's something
to be read. We used to raise a real alarm, but it seems
poll_for_input_1 ();
poll_suppress_count = old_poll_suppress_count;
}
- }
-
- /* 2000-09-28: In
- (let ((f (selected-frame)))
- (iconify-frame f)
- (raise-frame f))
-
- the frame is not raised with various window managers on
- FreeBSD, GNU/Linux and Solaris. It turns out that, for some
- unknown reason, the call to XtMapWidget is completely ignored.
- Mapping the widget a second time works. */
-
- if (!FRAME_VISIBLE_P (f) && --retry_count != 0)
- goto retry;
+ if (XPending (FRAME_X_DISPLAY (f)))
+ {
+ XEvent xev;
+ XNextEvent (FRAME_X_DISPLAY (f), &xev);
+ x_dispatch_event (&xev, FRAME_X_DISPLAY (f));
+ }
+ }
}
}
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
face. */
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
+ free_frame_faces (f);
if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
size_hints.height = FRAME_PIXEL_HEIGHT (f);
size_hints.width = FRAME_PIXEL_WIDTH (f);
- size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
- size_hints.height_inc = FRAME_LINE_HEIGHT (f);
+ size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
+ size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
+
size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
check_frame_size (f, &min_cols, &min_rows, 0);
+ if (frame_resize_pixelwise)
+ /* Needed to prevent a bad protocol error crash when making the
+ frame size very small. */
+ {
+ min_cols = 2 * min_cols;
+ min_rows = 2 * min_rows;
+ }
+
/* The window manager uses the base width hints to calculate the
current number of rows and columns in the frame while
resizing; min_width and min_height aren't useful for this
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
- size_hints.min_width = base_width + min_cols * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+ size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f);
+ size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f);
}
/* If we don't need the old flags, we don't need the old hint at all. */
if (STRINGP (value)
&& (!strcmp (SSDATA (value), "false")
|| !strcmp (SSDATA (value), "off")))
- use_xim = 0;
+ use_xim = false;
#else
if (STRINGP (value)
&& (!strcmp (SSDATA (value), "true")
|| !strcmp (SSDATA (value), "on")))
- use_xim = 1;
+ use_xim = true;
#endif
}