/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1989, 1993-2015 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2016 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.
+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
#include "lisp.h"
#include "blockinput.h"
-#include "syssignal.h"
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
-/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
-/* #include <sys/param.h> */
-
-#include "charset.h"
#include "character.h"
#include "coding.h"
+#include "composite.h"
#include "frame.h"
#include "dispextern.h"
+#include "xwidget.h"
#include "fontset.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
#include "emacs-icon.h"
-#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "keyboard.h"
-#include "intervals.h"
-#include "process.h"
#include "atimer.h"
-#include "keymap.h"
#include "font.h"
#include "xsettings.h"
-#include "xgselect.h"
#include "sysselect.h"
#include "menu.h"
#endif
#ifdef USE_X_TOOLKIT
-#if !defined (NO_EDITRES)
-#define HACK_EDITRES
-extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
-#endif /* not NO_EDITRES */
/* Include toolkit specific headers for the scroll bar widget. */
Lisp_Object acc = Qnil;
int count = SPECPDL_INDEX ();
- Fredisplay (Qt);
+ specbind (Qredisplay_dont_pause, Qt);
+ redisplay_preserve_echo_area (31);
f = XFRAME (XCAR (frames));
frames = XCDR (frames);
cr = cairo_create (surface);
cairo_surface_destroy (surface);
record_unwind_protect (x_cr_destroy, make_save_ptr (cr));
- unblock_input ();
while (1)
{
- QUIT;
-
- block_input ();
x_free_cr_resources (f);
FRAME_CR_CONTEXT (f) = cr;
x_clear_area (f, 0, 0, width, height);
expose_frame (f, 0, 0, width, height);
FRAME_CR_CONTEXT (f) = NULL;
- unblock_input ();
if (NILP (frames))
break;
- block_input ();
cairo_surface_show_page (surface);
f = XFRAME (XCAR (frames));
frames = XCDR (frames);
height = FRAME_PIXEL_HEIGHT (f);
if (surface_set_size_func)
(*surface_set_size_func) (surface, width, height);
+
unblock_input ();
+ QUIT;
+ block_input ();
}
#ifdef CAIRO_HAS_PNG_FUNCTIONS
if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
{
- block_input ();
cairo_surface_flush (surface);
cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
- unblock_input ();
}
#endif
+ unblock_input ();
+
unbind_to (count, Qnil);
return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct face *face;
- face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+ face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
if (face)
XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
face->foreground);
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_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);
+ struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
+ struct face *face_first
+ = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+ struct face *face_last
+ = FACE_FROM_ID_OR_NULL (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
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_X_DISPLAY (f);
- Window window = FRAME_X_WINDOW (f);
GC gc = f->output_data.x->normal_gc;
struct face *face = p->face;
#else /* not USE_CAIRO */
if (p->which)
{
+ Window window = FRAME_X_WINDOW (f);
char *bits;
Pixmap pixmap, clipmask = (Pixmap) 0;
int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
/* What face has to be used last for the mouse face? */
face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
- face = FACE_FROM_ID (s->f, face_id);
+ face = FACE_FROM_ID_OR_NULL (s->f, face_id);
if (face == NULL)
face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
x_color_cells (Display *dpy, int *ncells)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+ eassume (dpyinfo);
if (dpyinfo->color_cells == NULL)
{
the 0xff00 we'd get by just zero-filling the lower bits.
We generate a 32-bit scaled-up value and shift it, in case
- the bit count doesn't divide 16 evently (e.g., when dealing
+ the bit count doesn't divide 16 evenly (e.g., when dealing
with a 3-3-2 bit RGB display), to get more of the lower bits
correct.
equal to a cached pixel color recorded earlier, there was a
change in the colormap, so clear the color cache. */
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
- XColor *cached_color;
+ eassume (dpyinfo);
- if (dpyinfo->color_cells
- && (cached_color = &dpyinfo->color_cells[color->pixel],
- (cached_color->red != color->red
- || cached_color->blue != color->blue
- || cached_color->green != color->green)))
+ if (dpyinfo->color_cells)
{
- xfree (dpyinfo->color_cells);
- dpyinfo->color_cells = NULL;
- dpyinfo->ncolor_cells = 0;
+ XColor *cached_color = &dpyinfo->color_cells[color->pixel];
+ if (cached_color->red != color->red
+ || cached_color->blue != color->blue
+ || cached_color->green != color->green)
+ {
+ xfree (dpyinfo->color_cells);
+ dpyinfo->color_cells = NULL;
+ dpyinfo->ncolor_cells = 0;
+ }
}
}
x_draw_image_glyph_string (s);
break;
+ case XWIDGET_GLYPH:
+ x_draw_xwidget_glyph_string (s);
+ break;
+
case STRETCH_GLYPH:
x_draw_stretch_glyph_string (s);
break;
/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
If they are <= 0, this is probably an error. */
-static void
+static ATTRIBUTE_UNUSED void
x_clear_area1 (Display *dpy, Window window,
int x, int y, int width, int height, int exposures)
{
XClearArea (dpy, window, x, y, width, height, exposures);
}
-
void
x_clear_area (struct frame *f, int x, int y, int width, int height)
{
goto done;
}
-#ifdef HACK_EDITRES
+#ifdef X_TOOLKIT_EDITRES
if (event->xclient.message_type == dpyinfo->Xatom_editres)
{
f = any;
NULL, (XEvent *) event, NULL);
goto done;
}
-#endif /* HACK_EDITRES */
+#endif /* X_TOOLKIT_EDITRES */
if (event->xclient.message_type == dpyinfo->Xatom_DONE
|| event->xclient.message_type == dpyinfo->Xatom_PAGE)
/* Force a redisplay sooner or later to update the
frame titles in case this is the second frame. */
record_asynch_buffer_change ();
-
-#ifdef USE_GTK
- xg_frame_resized (f, -1, -1);
-#endif
}
goto OTHER;
if (cursor_glyph == NULL)
return;
+ /* Experimental avoidance of cursor on xwidget. */
+ if (cursor_glyph->type == XWIDGET_GLYPH)
+ return;
+
/* If on an image, draw like a normal cursor. That's usually better
visible than drawing a bar, esp. if the image is large so that
the bar might not be in the window. */
/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
the text of an error message that lead to the connection loss. */
-static void
+static _Noreturn void
x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
unbind_to (idx, Qnil);
clear_waiting_for_input ();
- /* Tell GCC not to suggest attribute 'noreturn' for this function. */
- IF_LINT (if (! terminal_list) return; )
-
/* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
longjmp), because returning from this function would get us back into
Xlib's code which will directly call `exit'. */
It kills all frames on the display that we lost touch with.
If that was the only one, it prints an error message and kills Emacs. */
-static int
+static _Noreturn int
x_io_error_quitter (Display *display)
{
char buf[256];
snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
DisplayString (display));
x_connection_closed (display, buf, true);
- return 0;
+ assume (false);
}
\f
/* Changing the font of the frame. */
int *size_state,
bool *sticky)
{
- Atom actual_type;
- unsigned long actual_size, bytes_remaining;
- int i, rc, actual_format;
+ unsigned long actual_size;
+ int i;
bool is_hidden = false;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
long max_len = 65536;
+ Atom target_type = XA_ATOM;
+ /* If XCB is available, we can avoid three XSync calls. */
+#ifdef USE_XCB
+ xcb_get_property_cookie_t prop_cookie;
+ xcb_get_property_reply_t *prop;
+ xcb_atom_t *reply_data;
+#else
Display *dpy = FRAME_X_DISPLAY (f);
+ unsigned long bytes_remaining;
+ int rc, actual_format;
+ Atom actual_type;
unsigned char *tmp_data = NULL;
- Atom target_type = XA_ATOM;
+ Atom *reply_data;
+#endif
*sticky = false;
*size_state = FULLSCREEN_NONE;
block_input ();
+
+#ifdef USE_XCB
+ prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
+ dpyinfo->Xatom_net_wm_state,
+ target_type, 0, max_len);
+ prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
+ if (prop && prop->type == target_type)
+ {
+ int actual_bytes = xcb_get_property_value_length (prop);
+ eassume (0 <= actual_bytes);
+ actual_size = actual_bytes / sizeof *reply_data;
+ reply_data = xcb_get_property_value (prop);
+ }
+ else
+ {
+ actual_size = 0;
+ is_hidden = FRAME_ICONIFIED_P (f);
+ }
+#else
x_catch_errors (dpy);
rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
0, max_len, False, target_type,
&actual_type, &actual_format, &actual_size,
&bytes_remaining, &tmp_data);
- if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
+ if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
+ reply_data = (Atom *) tmp_data;
+ else
{
- if (tmp_data) XFree (tmp_data);
- x_uncatch_errors ();
- unblock_input ();
- return !FRAME_ICONIFIED_P (f);
+ actual_size = 0;
+ is_hidden = FRAME_ICONIFIED_P (f);
}
x_uncatch_errors ();
+#endif
for (i = 0; i < actual_size; ++i)
{
- Atom a = ((Atom*)tmp_data)[i];
+ Atom a = reply_data[i];
if (a == dpyinfo->Xatom_net_wm_state_hidden)
is_hidden = true;
else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
*sticky = true;
}
+#ifdef USE_XCB
+ free (prop);
+#else
if (tmp_data) XFree (tmp_data);
+#endif
+
unblock_input ();
return ! is_hidden;
}
cancel_mouse_face (f);
unblock_input ();
+
+ do_pending_window_change (false);
}
/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
- ptrdiff_t lim;
+#ifdef USE_XCB
+ xcb_connection_t *xcb_conn;
+#endif
block_input ();
return 0;
}
+#ifdef USE_XCB
+ xcb_conn = XGetXCBConnection (dpy);
+ if (xcb_conn == 0)
+ {
+#ifdef USE_GTK
+ xg_display_close (dpy);
+#else
+#ifdef USE_X_TOOLKIT
+ XtCloseDisplay (dpy);
+#else
+ XCloseDisplay (dpy);
+#endif
+#endif /* ! USE_GTK */
+
+ unblock_input ();
+ return 0;
+ }
+#endif
+
/* We have definitely succeeded. Record the new connection. */
dpyinfo = xzalloc (sizeof *dpyinfo);
dpyinfo->name_list_element = Fcons (display_name, Qnil);
dpyinfo->display = dpy;
dpyinfo->connection = ConnectionNumber (dpyinfo->display);
+#ifdef USE_XCB
+ dpyinfo->xcb_connection = xcb_conn;
+#endif
+
+ /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ dpyinfo->smallest_font_height = 1;
+ dpyinfo->smallest_char_width = 1;
/* Set the name of the terminal. */
terminal->name = xlispstrdup (display_name);
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
- lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
Lisp_Object system_name = Fsystem_name ();
- if (lim - SBYTES (Vinvocation_name) < SBYTES (system_name))
+ ptrdiff_t nbytes;
+ if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
+ &nbytes))
memory_full (SIZE_MAX);
dpyinfo->x_id = ++x_display_id;
- dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
- + SBYTES (system_name) + 2);
+ dpyinfo->x_id_name = xmalloc (nbytes);
char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
*nametail++ = '@';
lispstpcpy (nametail, system_name);