Reimplement auto-saving to visited files
[emacs.git] / src / xterm.c
blob3de1ffea90017071cfb1b8932477295c89bb74fb
1 /* X Communication module for terminals which understand the X protocol.
3 Copyright (C) 1989, 1993-2017 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
21 /* Xt features made by Fred Pierresteguy. */
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #ifdef USE_CAIRO
27 #include <math.h>
28 #endif
30 #include "lisp.h"
31 #include "blockinput.h"
33 /* This may include sys/types.h, and that somehow loses
34 if this is not done before the other system files. */
35 #include "xterm.h"
36 #include <X11/cursorfont.h>
38 /* If we have Xfixes extension, use it for pointer blanking. */
39 #ifdef HAVE_XFIXES
40 #include <X11/extensions/Xfixes.h>
41 #endif
43 /* Using Xft implies that XRender is available. */
44 #ifdef HAVE_XFT
45 #include <X11/extensions/Xrender.h>
46 #endif
48 #ifdef HAVE_XDBE
49 #include <X11/extensions/Xdbe.h>
50 #endif
52 /* Load sys/types.h if not already loaded.
53 In some systems loading it twice is suicidal. */
54 #ifndef makedev
55 #include <sys/types.h>
56 #endif /* makedev */
58 #include <sys/ioctl.h>
60 #include "systime.h"
62 #include <fcntl.h>
63 #include <errno.h>
64 #include <sys/stat.h>
65 #include "character.h"
66 #include "coding.h"
67 #include "composite.h"
68 #include "frame.h"
69 #include "dispextern.h"
70 #include "xwidget.h"
71 #include "fontset.h"
72 #include "termhooks.h"
73 #include "termopts.h"
74 #include "termchar.h"
75 #include "emacs-icon.h"
76 #include "buffer.h"
77 #include "window.h"
78 #include "keyboard.h"
79 #include "atimer.h"
80 #include "font.h"
81 #include "xsettings.h"
82 #include "sysselect.h"
83 #include "menu.h"
85 #ifdef USE_X_TOOLKIT
86 #include <X11/Shell.h>
87 #endif
89 #include <unistd.h>
91 #ifdef USE_GTK
92 #include "gtkutil.h"
93 #ifdef HAVE_GTK3
94 #include <X11/Xproto.h>
95 #endif
96 #endif
98 #if defined (USE_LUCID) || defined (USE_MOTIF)
99 #include "../lwlib/xlwmenu.h"
100 #endif
102 #ifdef USE_X_TOOLKIT
104 /* Include toolkit specific headers for the scroll bar widget. */
106 #ifdef USE_TOOLKIT_SCROLL_BARS
107 #if defined USE_MOTIF
108 #include <Xm/Xm.h> /* For LESSTIF_VERSION */
109 #include <Xm/ScrollBar.h>
110 #else /* !USE_MOTIF i.e. use Xaw */
112 #ifdef HAVE_XAW3D
113 #include <X11/Xaw3d/Simple.h>
114 #include <X11/Xaw3d/Scrollbar.h>
115 #include <X11/Xaw3d/ThreeD.h>
116 #else /* !HAVE_XAW3D */
117 #include <X11/Xaw/Simple.h>
118 #include <X11/Xaw/Scrollbar.h>
119 #endif /* !HAVE_XAW3D */
120 #ifndef XtNpickTop
121 #define XtNpickTop "pickTop"
122 #endif /* !XtNpickTop */
123 #endif /* !USE_MOTIF */
124 #endif /* USE_TOOLKIT_SCROLL_BARS */
126 #endif /* USE_X_TOOLKIT */
128 #ifdef USE_X_TOOLKIT
129 #include "widget.h"
130 #ifndef XtNinitialState
131 #define XtNinitialState "initialState"
132 #endif
133 #endif
135 #include "bitmaps/gray.xbm"
137 #ifdef HAVE_XKB
138 #include <X11/XKBlib.h>
139 #endif
141 /* Default to using XIM if available. */
142 #ifdef USE_XIM
143 bool use_xim = true;
144 #else
145 bool use_xim = false; /* configure --without-xim */
146 #endif
148 /* Non-zero means that a HELP_EVENT has been generated since Emacs
149 start. */
151 static bool any_help_event_p;
153 /* This is a chain of structures for all the X displays currently in
154 use. */
156 struct x_display_info *x_display_list;
158 #ifdef USE_X_TOOLKIT
160 /* The application context for Xt use. */
161 XtAppContext Xt_app_con;
162 static String Xt_default_resources[] = {0};
164 /* Non-zero means user is interacting with a toolkit scroll bar. */
165 static bool toolkit_scroll_bar_interaction;
167 #endif /* USE_X_TOOLKIT */
169 /* Non-zero timeout value means ignore next mouse click if it arrives
170 before that timeout elapses (i.e. as part of the same sequence of
171 events resulting from clicking on a frame to select it). */
173 static Time ignore_next_mouse_click_timeout;
175 /* Used locally within XTread_socket. */
177 static int x_noop_count;
179 #ifdef USE_GTK
180 /* The name of the Emacs icon file. */
181 static Lisp_Object xg_default_icon_file;
182 #endif
184 /* Some functions take this as char *, not const char *. */
185 static char emacs_class[] = EMACS_CLASS;
187 enum xembed_info
189 XEMBED_MAPPED = 1 << 0
192 enum xembed_message
194 XEMBED_EMBEDDED_NOTIFY = 0,
195 XEMBED_WINDOW_ACTIVATE = 1,
196 XEMBED_WINDOW_DEACTIVATE = 2,
197 XEMBED_REQUEST_FOCUS = 3,
198 XEMBED_FOCUS_IN = 4,
199 XEMBED_FOCUS_OUT = 5,
200 XEMBED_FOCUS_NEXT = 6,
201 XEMBED_FOCUS_PREV = 7,
203 XEMBED_MODALITY_ON = 10,
204 XEMBED_MODALITY_OFF = 11,
205 XEMBED_REGISTER_ACCELERATOR = 12,
206 XEMBED_UNREGISTER_ACCELERATOR = 13,
207 XEMBED_ACTIVATE_ACCELERATOR = 14
210 static void x_free_cr_resources (struct frame *);
211 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
212 static void x_raise_frame (struct frame *);
213 static void x_lower_frame (struct frame *);
214 static int x_io_error_quitter (Display *);
215 static struct terminal *x_create_terminal (struct x_display_info *);
216 static void x_frame_rehighlight (struct x_display_info *);
218 static void x_clip_to_row (struct window *, struct glyph_row *,
219 enum glyph_row_area, GC);
220 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
221 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
222 enum scroll_bar_part *,
223 Lisp_Object *, Lisp_Object *,
224 Time *);
225 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
226 enum scroll_bar_part *,
227 Lisp_Object *, Lisp_Object *,
228 Time *);
229 static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
230 static void x_check_fullscreen (struct frame *);
231 static void x_check_expected_move (struct frame *, int, int);
232 static void x_sync_with_move (struct frame *, int, int, bool);
233 static int handle_one_xevent (struct x_display_info *,
234 const XEvent *, int *,
235 struct input_event *);
236 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
237 static int x_dispatch_event (XEvent *, Display *);
238 #endif
239 static void x_wm_set_window_state (struct frame *, int);
240 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
241 static void x_initialize (void);
243 static bool get_current_wm_state (struct frame *, Window, int *, bool *);
245 /* Flush display of frame F. */
247 static void
248 x_flush (struct frame *f)
250 eassert (f && FRAME_X_P (f));
251 /* Don't call XFlush when it is not safe to redisplay; the X
252 connection may be broken. */
253 if (!NILP (Vinhibit_redisplay))
254 return;
256 block_input ();
257 XFlush (FRAME_X_DISPLAY (f));
258 unblock_input ();
262 /* Remove calls to XFlush by defining XFlush to an empty replacement.
263 Calls to XFlush should be unnecessary because the X output buffer
264 is flushed automatically as needed by calls to XPending,
265 XNextEvent, or XWindowEvent according to the XFlush man page.
266 XTread_socket calls XPending. Removing XFlush improves
267 performance. */
269 #define XFlush(DISPLAY) (void) 0
272 /***********************************************************************
273 Debugging
274 ***********************************************************************/
276 #if false
278 /* This is a function useful for recording debugging information about
279 the sequence of occurrences in this file. */
281 struct record
283 char *locus;
284 int type;
287 struct record event_record[100];
289 int event_record_index;
291 void
292 record_event (char *locus, int type)
294 if (event_record_index == ARRAYELTS (event_record))
295 event_record_index = 0;
297 event_record[event_record_index].locus = locus;
298 event_record[event_record_index].type = type;
299 event_record_index++;
302 #endif
304 #ifdef USE_CAIRO
306 #define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
307 #define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
309 static struct x_gc_ext_data *
310 x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
312 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
313 XEDataObject object;
314 XExtData **head, *ext_data;
316 object.gc = gc;
317 head = XEHeadOfExtensionList (object);
318 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
319 if (ext_data == NULL)
321 if (!create_if_not_found_p)
322 return NULL;
323 else
325 ext_data = xzalloc (sizeof (*ext_data));
326 ext_data->number = dpyinfo->ext_codes->extension;
327 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
328 XAddToExtensionList (head, ext_data);
331 return (struct x_gc_ext_data *) ext_data->private_data;
334 static void
335 x_extension_initialize (struct x_display_info *dpyinfo)
337 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
339 dpyinfo->ext_codes = ext_codes;
342 static void
343 x_cr_destroy_surface (struct frame *f)
345 if (FRAME_CR_SURFACE (f))
347 cairo_t *cr = FRAME_CR_CONTEXT (f);
348 cairo_surface_destroy (FRAME_CR_SURFACE (f));
349 FRAME_CR_SURFACE (f) = 0;
350 if (cr) cairo_destroy (cr);
351 FRAME_CR_CONTEXT (f) = NULL;
355 cairo_t *
356 x_begin_cr_clip (struct frame *f, GC gc)
358 cairo_t *cr = FRAME_CR_CONTEXT (f);
360 if (!cr)
363 if (! FRAME_CR_SURFACE (f))
365 cairo_surface_t *surface;
366 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
367 FRAME_X_DRAWABLE (f),
368 FRAME_DISPLAY_INFO (f)->visual,
369 FRAME_PIXEL_WIDTH (f),
370 FRAME_PIXEL_HEIGHT (f));
371 cr = cairo_create (surface);
372 cairo_surface_destroy (surface);
374 else
375 cr = cairo_create (FRAME_CR_SURFACE (f));
376 FRAME_CR_CONTEXT (f) = cr;
378 cairo_save (cr);
380 if (gc)
382 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
384 if (gc_ext && gc_ext->n_clip_rects)
386 int i;
388 for (i = 0; i < gc_ext->n_clip_rects; i++)
389 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
390 gc_ext->clip_rects[i].y,
391 gc_ext->clip_rects[i].width,
392 gc_ext->clip_rects[i].height);
393 cairo_clip (cr);
397 return cr;
400 void
401 x_end_cr_clip (struct frame *f)
403 cairo_restore (FRAME_CR_CONTEXT (f));
406 void
407 x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
409 XGCValues xgcv;
410 XColor color;
412 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
413 color.pixel = xgcv.foreground;
414 x_query_color (f, &color);
415 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
416 color.green / 65535.0, color.blue / 65535.0);
419 void
420 x_set_cr_source_with_gc_background (struct frame *f, GC gc)
422 XGCValues xgcv;
423 XColor color;
425 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
426 color.pixel = xgcv.background;
427 x_query_color (f, &color);
428 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
429 color.green / 65535.0, color.blue / 65535.0);
432 /* Fringe bitmaps. */
434 static int max_fringe_bmp = 0;
435 static cairo_pattern_t **fringe_bmp = 0;
437 static void
438 x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
440 int i, stride;
441 cairo_surface_t *surface;
442 unsigned char *data;
443 cairo_pattern_t *pattern;
445 if (which >= max_fringe_bmp)
447 i = max_fringe_bmp;
448 max_fringe_bmp = which + 20;
449 fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *));
450 while (i < max_fringe_bmp)
451 fringe_bmp[i++] = 0;
454 block_input ();
456 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
457 stride = cairo_image_surface_get_stride (surface);
458 data = cairo_image_surface_get_data (surface);
460 for (i = 0; i < h; i++)
462 *((unsigned short *) data) = bits[i];
463 data += stride;
466 cairo_surface_mark_dirty (surface);
467 pattern = cairo_pattern_create_for_surface (surface);
468 cairo_surface_destroy (surface);
470 unblock_input ();
472 fringe_bmp[which] = pattern;
475 static void
476 x_cr_destroy_fringe_bitmap (int which)
478 if (which >= max_fringe_bmp)
479 return;
481 if (fringe_bmp[which])
483 block_input ();
484 cairo_pattern_destroy (fringe_bmp[which]);
485 unblock_input ();
487 fringe_bmp[which] = 0;
490 static void
491 x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
492 int src_x, int src_y, int width, int height,
493 int dest_x, int dest_y, bool overlay_p)
495 cairo_t *cr;
496 cairo_matrix_t matrix;
497 cairo_surface_t *surface;
498 cairo_format_t format;
500 cr = x_begin_cr_clip (f, gc);
501 if (overlay_p)
502 cairo_rectangle (cr, dest_x, dest_y, width, height);
503 else
505 x_set_cr_source_with_gc_background (f, gc);
506 cairo_rectangle (cr, dest_x, dest_y, width, height);
507 cairo_fill_preserve (cr);
509 cairo_clip (cr);
510 cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y);
511 cairo_pattern_set_matrix (image, &matrix);
512 cairo_pattern_get_surface (image, &surface);
513 format = cairo_image_surface_get_format (surface);
514 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
516 cairo_set_source (cr, image);
517 cairo_fill (cr);
519 else
521 x_set_cr_source_with_gc_foreground (f, gc);
522 cairo_mask (cr, image);
524 x_end_cr_clip (f);
527 void
528 x_cr_draw_frame (cairo_t *cr, struct frame *f)
530 int width, height;
532 width = FRAME_PIXEL_WIDTH (f);
533 height = FRAME_PIXEL_HEIGHT (f);
535 x_free_cr_resources (f);
536 FRAME_CR_CONTEXT (f) = cr;
537 x_clear_area (f, 0, 0, width, height);
538 expose_frame (f, 0, 0, width, height);
539 FRAME_CR_CONTEXT (f) = NULL;
542 static cairo_status_t
543 x_cr_accumulate_data (void *closure, const unsigned char *data,
544 unsigned int length)
546 Lisp_Object *acc = (Lisp_Object *) closure;
548 *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
550 return CAIRO_STATUS_SUCCESS;
553 static void
554 x_cr_destroy (Lisp_Object arg)
556 cairo_t *cr = (cairo_t *) XSAVE_POINTER (arg, 0);
558 block_input ();
559 cairo_destroy (cr);
560 unblock_input ();
563 Lisp_Object
564 x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
566 struct frame *f;
567 cairo_surface_t *surface;
568 cairo_t *cr;
569 int width, height;
570 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
571 Lisp_Object acc = Qnil;
572 int count = SPECPDL_INDEX ();
574 specbind (Qredisplay_dont_pause, Qt);
575 redisplay_preserve_echo_area (31);
577 f = XFRAME (XCAR (frames));
578 frames = XCDR (frames);
579 width = FRAME_PIXEL_WIDTH (f);
580 height = FRAME_PIXEL_HEIGHT (f);
582 block_input ();
583 #ifdef CAIRO_HAS_PDF_SURFACE
584 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
586 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
587 width, height);
588 surface_set_size_func = cairo_pdf_surface_set_size;
590 else
591 #endif
592 #ifdef CAIRO_HAS_PNG_FUNCTIONS
593 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
594 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
595 else
596 #endif
597 #ifdef CAIRO_HAS_PS_SURFACE
598 if (surface_type == CAIRO_SURFACE_TYPE_PS)
600 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
601 width, height);
602 surface_set_size_func = cairo_ps_surface_set_size;
604 else
605 #endif
606 #ifdef CAIRO_HAS_SVG_SURFACE
607 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
608 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
609 width, height);
610 else
611 #endif
612 abort ();
614 cr = cairo_create (surface);
615 cairo_surface_destroy (surface);
616 record_unwind_protect (x_cr_destroy, make_save_ptr (cr));
618 while (1)
620 x_free_cr_resources (f);
621 FRAME_CR_CONTEXT (f) = cr;
622 x_clear_area (f, 0, 0, width, height);
623 expose_frame (f, 0, 0, width, height);
624 FRAME_CR_CONTEXT (f) = NULL;
626 if (NILP (frames))
627 break;
629 cairo_surface_show_page (surface);
630 f = XFRAME (XCAR (frames));
631 frames = XCDR (frames);
632 width = FRAME_PIXEL_WIDTH (f);
633 height = FRAME_PIXEL_HEIGHT (f);
634 if (surface_set_size_func)
635 (*surface_set_size_func) (surface, width, height);
637 unblock_input ();
638 maybe_quit ();
639 block_input ();
642 #ifdef CAIRO_HAS_PNG_FUNCTIONS
643 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
645 cairo_surface_flush (surface);
646 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
648 #endif
649 unblock_input ();
651 unbind_to (count, Qnil);
653 return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
656 #endif /* USE_CAIRO */
658 static void
659 x_free_cr_resources (struct frame *f)
661 #ifdef USE_CAIRO
662 if (f == NULL)
664 Lisp_Object rest, frame;
665 FOR_EACH_FRAME (rest, frame)
666 if (FRAME_X_P (XFRAME (frame)))
667 x_free_cr_resources (XFRAME (frame));
669 else
671 cairo_t *cr = FRAME_CR_CONTEXT (f);
673 if (cr)
675 cairo_surface_t *surface = cairo_get_target (cr);
677 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
679 cairo_destroy (cr);
680 FRAME_CR_CONTEXT (f) = NULL;
684 #endif
687 static void
688 x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
690 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
691 #ifdef USE_CAIRO
692 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
695 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
697 gc_ext->n_clip_rects = n;
698 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
700 #endif
703 static void
704 x_reset_clip_rectangles (struct frame *f, GC gc)
706 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
707 #ifdef USE_CAIRO
709 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
711 if (gc_ext)
712 gc_ext->n_clip_rects = 0;
714 #endif
717 static void
718 x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
720 #ifdef USE_CAIRO
721 cairo_t *cr;
723 cr = x_begin_cr_clip (f, gc);
724 x_set_cr_source_with_gc_foreground (f, gc);
725 cairo_rectangle (cr, x, y, width, height);
726 cairo_fill (cr);
727 x_end_cr_clip (f);
728 #else
729 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
730 gc, x, y, width, height);
731 #endif
734 static void
735 x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
737 #ifdef USE_CAIRO
738 cairo_t *cr;
740 cr = x_begin_cr_clip (f, gc);
741 x_set_cr_source_with_gc_foreground (f, gc);
742 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
743 cairo_set_line_width (cr, 1);
744 cairo_stroke (cr);
745 x_end_cr_clip (f);
746 #else
747 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
748 gc, x, y, width, height);
749 #endif
752 static void
753 x_clear_window (struct frame *f)
755 #ifdef USE_CAIRO
756 cairo_t *cr;
758 cr = x_begin_cr_clip (f, NULL);
759 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
760 cairo_paint (cr);
761 x_end_cr_clip (f);
762 #else
763 if (FRAME_X_DOUBLE_BUFFERED_P (f))
764 x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
765 else
766 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
767 #endif
770 #ifdef USE_CAIRO
771 static void
772 x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
773 int width, int height, int top_p)
775 cairo_t *cr;
777 cr = x_begin_cr_clip (f, gc);
778 x_set_cr_source_with_gc_foreground (f, gc);
779 cairo_move_to (cr, top_p ? x : x + height, y);
780 cairo_line_to (cr, x, y + height);
781 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
782 cairo_line_to (cr, x + width, y);
783 cairo_fill (cr);
784 x_end_cr_clip (f);
787 enum corners
789 CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */
790 CORNER_BOTTOM_LEFT, /* pi/2 -> pi */
791 CORNER_TOP_LEFT, /* pi -> 3pi/2 */
792 CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */
793 CORNER_LAST
796 static void
797 x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
798 int width, int height,
799 double radius, double margin, int corners)
801 cairo_t *cr;
802 int i;
804 cr = x_begin_cr_clip (f, gc);
805 x_set_cr_source_with_gc_background (f, gc);
806 for (i = 0; i < CORNER_LAST; i++)
807 if (corners & (1 << i))
809 double xm, ym, xc, yc;
811 if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
812 xm = x - margin, xc = xm + radius;
813 else
814 xm = x + width + margin, xc = xm - radius;
815 if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
816 ym = y - margin, yc = ym + radius;
817 else
818 ym = y + height + margin, yc = ym - radius;
820 cairo_move_to (cr, xm, ym);
821 cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
823 cairo_clip (cr);
824 cairo_rectangle (cr, x, y, width, height);
825 cairo_fill (cr);
826 x_end_cr_clip (f);
829 static void
830 x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
831 int width, int height, int wave_length)
833 cairo_t *cr;
834 double dx = wave_length, dy = height - 1;
835 int xoffset, n;
837 cr = x_begin_cr_clip (f, gc);
838 x_set_cr_source_with_gc_foreground (f, gc);
839 cairo_rectangle (cr, x, y, width, height);
840 cairo_clip (cr);
842 if (x >= 0)
844 xoffset = x % (wave_length * 2);
845 if (xoffset == 0)
846 xoffset = wave_length * 2;
848 else
849 xoffset = x % (wave_length * 2) + wave_length * 2;
850 n = (width + xoffset) / wave_length + 1;
851 if (xoffset > wave_length)
853 xoffset -= wave_length;
854 --n;
855 y += height - 1;
856 dy = -dy;
859 cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
860 while (--n >= 0)
862 cairo_rel_line_to (cr, dx, dy);
863 dy = -dy;
865 cairo_set_line_width (cr, 1);
866 cairo_stroke (cr);
867 x_end_cr_clip (f);
869 #endif
872 /* Return the struct x_display_info corresponding to DPY. */
874 struct x_display_info *
875 x_display_info_for_display (Display *dpy)
877 struct x_display_info *dpyinfo;
879 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
880 if (dpyinfo->display == dpy)
881 return dpyinfo;
883 return 0;
886 static Window
887 x_find_topmost_parent (struct frame *f)
889 struct x_output *x = f->output_data.x;
890 Window win = None, wi = x->parent_desc;
891 Display *dpy = FRAME_X_DISPLAY (f);
893 while (wi != FRAME_DISPLAY_INFO (f)->root_window)
895 Window root;
896 Window *children;
897 unsigned int nchildren;
899 win = wi;
900 if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
901 XFree (children);
902 else
903 break;
906 return win;
909 #define OPAQUE 0xffffffff
911 void
912 x_set_frame_alpha (struct frame *f)
914 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
915 Display *dpy = FRAME_X_DISPLAY (f);
916 Window win = FRAME_OUTER_WINDOW (f);
917 double alpha = 1.0;
918 double alpha_min = 1.0;
919 unsigned long opac;
920 Window parent;
922 if (dpyinfo->x_highlight_frame == f)
923 alpha = f->alpha[0];
924 else
925 alpha = f->alpha[1];
927 if (FLOATP (Vframe_alpha_lower_limit))
928 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
929 else if (INTEGERP (Vframe_alpha_lower_limit))
930 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
932 if (alpha < 0.0)
933 return;
934 else if (alpha > 1.0)
935 alpha = 1.0;
936 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
937 alpha = alpha_min;
939 opac = alpha * OPAQUE;
941 x_catch_errors (dpy);
943 /* If there is a parent from the window manager, put the property there
944 also, to work around broken window managers that fail to do that.
945 Do this unconditionally as this function is called on reparent when
946 alpha has not changed on the frame. */
948 if (!FRAME_PARENT_FRAME (f))
950 parent = x_find_topmost_parent (f);
951 if (parent != None)
952 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
953 XA_CARDINAL, 32, PropModeReplace,
954 (unsigned char *) &opac, 1);
957 /* return unless necessary */
959 unsigned char *data;
960 Atom actual;
961 int rc, format;
962 unsigned long n, left;
964 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
965 0, 1, False, XA_CARDINAL,
966 &actual, &format, &n, &left,
967 &data);
969 if (rc == Success && actual != None)
971 unsigned long value = *(unsigned long *)data;
972 XFree (data);
973 if (value == opac)
975 x_uncatch_errors ();
976 return;
981 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
982 XA_CARDINAL, 32, PropModeReplace,
983 (unsigned char *) &opac, 1);
984 x_uncatch_errors ();
987 /***********************************************************************
988 Starting and ending an update
989 ***********************************************************************/
991 /* Start an update of frame F. This function is installed as a hook
992 for update_begin, i.e. it is called when update_begin is called.
993 This function is called prior to calls to x_update_window_begin for
994 each window being updated. Currently, there is nothing to do here
995 because all interesting stuff is done on a window basis. */
997 static void
998 x_update_begin (struct frame *f)
1000 #ifdef USE_CAIRO
1001 if (! NILP (tip_frame) && XFRAME (tip_frame) == f
1002 && ! FRAME_VISIBLE_P (f))
1003 return;
1005 if (! FRAME_CR_SURFACE (f))
1007 int width, height;
1008 #ifdef USE_GTK
1009 if (FRAME_GTK_WIDGET (f))
1011 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1012 width = gdk_window_get_width (w);
1013 height = gdk_window_get_height (w);
1015 else
1016 #endif
1018 width = FRAME_PIXEL_WIDTH (f);
1019 height = FRAME_PIXEL_HEIGHT (f);
1020 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1021 height += FRAME_TOOL_BAR_HEIGHT (f);
1022 if (! FRAME_EXTERNAL_MENU_BAR (f))
1023 height += FRAME_MENU_BAR_HEIGHT (f);
1026 if (width > 0 && height > 0)
1028 block_input();
1029 FRAME_CR_SURFACE (f) = cairo_image_surface_create
1030 (CAIRO_FORMAT_ARGB32, width, height);
1031 unblock_input();
1034 #endif /* USE_CAIRO */
1037 /* Start update of window W. */
1039 static void
1040 x_update_window_begin (struct window *w)
1042 struct frame *f = XFRAME (WINDOW_FRAME (w));
1043 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
1045 w->output_cursor = w->cursor;
1047 block_input ();
1049 if (f == hlinfo->mouse_face_mouse_frame)
1051 /* Don't do highlighting for mouse motion during the update. */
1052 hlinfo->mouse_face_defer = true;
1054 /* If F needs to be redrawn, simply forget about any prior mouse
1055 highlighting. */
1056 if (FRAME_GARBAGED_P (f))
1057 hlinfo->mouse_face_window = Qnil;
1060 unblock_input ();
1064 /* Draw a vertical window border from (x,y0) to (x,y1) */
1066 static void
1067 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
1069 struct frame *f = XFRAME (WINDOW_FRAME (w));
1070 struct face *face;
1072 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
1073 if (face)
1074 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
1075 face->foreground);
1077 #ifdef USE_CAIRO
1078 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
1079 #else
1080 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
1081 f->output_data.x->normal_gc, x, y0, x, y1);
1082 #endif
1085 /* Draw a window divider from (x0,y0) to (x1,y1) */
1087 static void
1088 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
1090 struct frame *f = XFRAME (WINDOW_FRAME (w));
1091 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
1092 struct face *face_first
1093 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
1094 struct face *face_last
1095 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
1096 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
1097 unsigned long color_first = (face_first
1098 ? face_first->foreground
1099 : FRAME_FOREGROUND_PIXEL (f));
1100 unsigned long color_last = (face_last
1101 ? face_last->foreground
1102 : FRAME_FOREGROUND_PIXEL (f));
1103 Display *display = FRAME_X_DISPLAY (f);
1105 if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
1106 /* Vertical. */
1108 XSetForeground (display, f->output_data.x->normal_gc, color_first);
1109 x_fill_rectangle (f, f->output_data.x->normal_gc,
1110 x0, y0, 1, y1 - y0);
1111 XSetForeground (display, f->output_data.x->normal_gc, color);
1112 x_fill_rectangle (f, f->output_data.x->normal_gc,
1113 x0 + 1, y0, x1 - x0 - 2, y1 - y0);
1114 XSetForeground (display, f->output_data.x->normal_gc, color_last);
1115 x_fill_rectangle (f, f->output_data.x->normal_gc,
1116 x1 - 1, y0, 1, y1 - y0);
1118 else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
1119 /* Horizontal. */
1121 XSetForeground (display, f->output_data.x->normal_gc, color_first);
1122 x_fill_rectangle (f, f->output_data.x->normal_gc,
1123 x0, y0, x1 - x0, 1);
1124 XSetForeground (display, f->output_data.x->normal_gc, color);
1125 x_fill_rectangle (f, f->output_data.x->normal_gc,
1126 x0, y0 + 1, x1 - x0, y1 - y0 - 2);
1127 XSetForeground (display, f->output_data.x->normal_gc, color_last);
1128 x_fill_rectangle (f, f->output_data.x->normal_gc,
1129 x0, y1 - 1, x1 - x0, 1);
1131 else
1133 XSetForeground (display, f->output_data.x->normal_gc, color);
1134 x_fill_rectangle (f, f->output_data.x->normal_gc,
1135 x0, y0, x1 - x0, y1 - y0);
1139 /* End update of window W.
1141 Draw vertical borders between horizontally adjacent windows, and
1142 display W's cursor if CURSOR_ON_P is non-zero.
1144 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1145 glyphs in mouse-face were overwritten. In that case we have to
1146 make sure that the mouse-highlight is properly redrawn.
1148 W may be a menu bar pseudo-window in case we don't have X toolkit
1149 support. Such windows don't have a cursor, so don't display it
1150 here. */
1152 static void
1153 x_update_window_end (struct window *w, bool cursor_on_p,
1154 bool mouse_face_overwritten_p)
1156 if (!w->pseudo_window_p)
1158 block_input ();
1160 if (cursor_on_p)
1161 display_and_set_cursor (w, true,
1162 w->output_cursor.hpos, w->output_cursor.vpos,
1163 w->output_cursor.x, w->output_cursor.y);
1165 if (draw_window_fringes (w, true))
1167 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
1168 x_draw_right_divider (w);
1169 else
1170 x_draw_vertical_border (w);
1173 unblock_input ();
1176 /* If a row with mouse-face was overwritten, arrange for
1177 XTframe_up_to_date to redisplay the mouse highlight. */
1178 if (mouse_face_overwritten_p)
1180 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
1182 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
1183 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
1184 hlinfo->mouse_face_window = Qnil;
1188 /* Show the frame back buffer. If frame is double-buffered,
1189 atomically publish to the user's screen graphics updates made since
1190 the last call to show_back_buffer. */
1191 static void
1192 show_back_buffer (struct frame *f)
1194 block_input ();
1195 if (FRAME_X_DOUBLE_BUFFERED_P (f))
1197 #ifdef HAVE_XDBE
1198 XdbeSwapInfo swap_info;
1199 memset (&swap_info, 0, sizeof (swap_info));
1200 swap_info.swap_window = FRAME_X_WINDOW (f);
1201 swap_info.swap_action = XdbeCopied;
1202 XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
1203 #else
1204 eassert (!"should have back-buffer only with XDBE");
1205 #endif
1207 FRAME_X_NEED_BUFFER_FLIP (f) = false;
1208 unblock_input ();
1211 /* Updates back buffer and flushes changes to display. Called from
1212 minibuf read code. Note that we display the back buffer even if
1213 buffer flipping is blocked. */
1214 static void
1215 x_flip_and_flush (struct frame *f)
1217 block_input ();
1218 if (FRAME_X_NEED_BUFFER_FLIP (f))
1219 show_back_buffer (f);
1220 x_flush (f);
1221 unblock_input ();
1224 /* End update of frame F. This function is installed as a hook in
1225 update_end. */
1227 static void
1228 x_update_end (struct frame *f)
1230 /* Mouse highlight may be displayed again. */
1231 MOUSE_HL_INFO (f)->mouse_face_defer = false;
1233 #ifdef USE_CAIRO
1234 if (FRAME_CR_SURFACE (f))
1236 cairo_t *cr = 0;
1237 block_input();
1238 #if defined (USE_GTK) && defined (HAVE_GTK3)
1239 if (FRAME_GTK_WIDGET (f))
1241 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1242 cr = gdk_cairo_create (w);
1244 else
1245 #endif
1247 cairo_surface_t *surface;
1248 int width = FRAME_PIXEL_WIDTH (f);
1249 int height = FRAME_PIXEL_HEIGHT (f);
1250 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1251 height += FRAME_TOOL_BAR_HEIGHT (f);
1252 if (! FRAME_EXTERNAL_MENU_BAR (f))
1253 height += FRAME_MENU_BAR_HEIGHT (f);
1254 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
1255 FRAME_X_DRAWABLE (f),
1256 FRAME_DISPLAY_INFO (f)->visual,
1257 width,
1258 height);
1259 cr = cairo_create (surface);
1260 cairo_surface_destroy (surface);
1263 cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
1264 cairo_paint (cr);
1265 cairo_destroy (cr);
1266 unblock_input ();
1268 #endif
1270 #ifndef XFlush
1271 block_input ();
1272 XFlush (FRAME_X_DISPLAY (f));
1273 unblock_input ();
1274 #endif
1277 /* This function is called from various places in xdisp.c
1278 whenever a complete update has been performed. */
1280 static void
1281 XTframe_up_to_date (struct frame *f)
1283 eassert (FRAME_X_P (f));
1284 block_input ();
1285 FRAME_MOUSE_UPDATE (f);
1286 if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
1287 show_back_buffer (f);
1288 unblock_input ();
1291 static void
1292 XTbuffer_flipping_unblocked_hook (struct frame *f)
1294 if (FRAME_X_NEED_BUFFER_FLIP (f))
1295 show_back_buffer (f);
1299 * x_clear_under_internal_border:
1301 * Clear area of frame F's internal border. If the internal border face
1302 * of F has been specified (is not null), fill the area with that face.
1304 void
1305 x_clear_under_internal_border (struct frame *f)
1307 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
1309 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
1310 int width = FRAME_PIXEL_WIDTH (f);
1311 int height = FRAME_PIXEL_HEIGHT (f);
1312 #ifdef USE_GTK
1313 int margin = 0;
1314 #else
1315 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
1316 #endif
1317 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
1319 block_input ();
1321 if (face)
1323 unsigned long color = face->background;
1324 Display *display = FRAME_X_DISPLAY (f);
1325 GC gc = f->output_data.x->normal_gc;
1327 XSetForeground (display, gc, color);
1328 x_fill_rectangle (f, gc, 0, margin, width, border);
1329 x_fill_rectangle (f, gc, 0, 0, border, height);
1330 x_fill_rectangle (f, gc, width - border, 0, border, height);
1331 x_fill_rectangle (f, gc, 0, height - border, width, border);
1332 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
1334 else
1336 x_clear_area (f, 0, 0, border, height);
1337 x_clear_area (f, 0, margin, width, border);
1338 x_clear_area (f, width - border, 0, border, height);
1339 x_clear_area (f, 0, height - border, width, border);
1342 unblock_input ();
1346 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1347 arrow bitmaps, or clear the fringes if no bitmaps are required
1348 before DESIRED_ROW is made current. This function is called from
1349 update_window_line only if it is known that there are differences
1350 between bitmaps to be drawn between current row and DESIRED_ROW. */
1352 static void
1353 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
1355 eassert (w);
1357 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1358 desired_row->redraw_fringe_bitmaps_p = true;
1360 #ifdef USE_X_TOOLKIT
1361 /* When a window has disappeared, make sure that no rest of
1362 full-width rows stays visible in the internal border. Could
1363 check here if updated window is the leftmost/rightmost window,
1364 but I guess it's not worth doing since vertically split windows
1365 are almost never used, internal border is rarely set, and the
1366 overhead is very small. */
1368 struct frame *f;
1369 int width, height;
1371 if (windows_or_buffers_changed
1372 && desired_row->full_width_p
1373 && (f = XFRAME (w->frame),
1374 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1375 width != 0)
1376 && (height = desired_row->visible_height,
1377 height > 0))
1379 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1380 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
1382 block_input ();
1383 if (face)
1385 unsigned long color = face->background;
1386 Display *display = FRAME_X_DISPLAY (f);
1388 XSetForeground (display, f->output_data.x->normal_gc, color);
1389 x_fill_rectangle (f, f->output_data.x->normal_gc,
1390 0, y, width, height);
1391 x_fill_rectangle (f, f->output_data.x->normal_gc,
1392 FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1394 else
1396 x_clear_area (f, 0, y, width, height);
1397 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1399 unblock_input ();
1402 #endif
1405 static void
1406 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
1408 struct frame *f = XFRAME (WINDOW_FRAME (w));
1409 Display *display = FRAME_X_DISPLAY (f);
1410 GC gc = f->output_data.x->normal_gc;
1411 struct face *face = p->face;
1413 /* Must clip because of partially visible lines. */
1414 x_clip_to_row (w, row, ANY_AREA, gc);
1416 if (p->bx >= 0 && !p->overlay_p)
1418 /* In case the same realized face is used for fringes and
1419 for something displayed in the text (e.g. face `region' on
1420 mono-displays, the fill style may have been changed to
1421 FillSolid in x_draw_glyph_string_background. */
1422 if (face->stipple)
1423 XSetFillStyle (display, face->gc, FillOpaqueStippled);
1424 else
1425 XSetForeground (display, face->gc, face->background);
1427 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
1429 if (!face->stipple)
1430 XSetForeground (display, face->gc, face->foreground);
1433 #ifdef USE_CAIRO
1434 if (p->which && p->which < max_fringe_bmp)
1436 XGCValues gcv;
1438 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
1439 XSetForeground (display, gc, (p->cursor_p
1440 ? (p->overlay_p ? face->background
1441 : f->output_data.x->cursor_pixel)
1442 : face->foreground));
1443 XSetBackground (display, gc, face->background);
1444 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
1445 p->wd, p->h, p->x, p->y, p->overlay_p);
1446 XSetForeground (display, gc, gcv.foreground);
1447 XSetBackground (display, gc, gcv.background);
1449 #else /* not USE_CAIRO */
1450 if (p->which)
1452 Drawable drawable = FRAME_X_DRAWABLE (f);
1453 char *bits;
1454 Pixmap pixmap, clipmask = (Pixmap) 0;
1455 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
1456 XGCValues gcv;
1458 if (p->wd > 8)
1459 bits = (char *) (p->bits + p->dh);
1460 else
1461 bits = (char *) p->bits + p->dh;
1463 /* Draw the bitmap. I believe these small pixmaps can be cached
1464 by the server. */
1465 pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
1466 (p->cursor_p
1467 ? (p->overlay_p ? face->background
1468 : f->output_data.x->cursor_pixel)
1469 : face->foreground),
1470 face->background, depth);
1472 if (p->overlay_p)
1474 clipmask = XCreatePixmapFromBitmapData (display,
1475 FRAME_DISPLAY_INFO (f)->root_window,
1476 bits, p->wd, p->h,
1477 1, 0, 1);
1478 gcv.clip_mask = clipmask;
1479 gcv.clip_x_origin = p->x;
1480 gcv.clip_y_origin = p->y;
1481 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
1484 XCopyArea (display, pixmap, drawable, gc, 0, 0,
1485 p->wd, p->h, p->x, p->y);
1486 XFreePixmap (display, pixmap);
1488 if (p->overlay_p)
1490 gcv.clip_mask = (Pixmap) 0;
1491 XChangeGC (display, gc, GCClipMask, &gcv);
1492 XFreePixmap (display, clipmask);
1495 #endif /* not USE_CAIRO */
1497 x_reset_clip_rectangles (f, gc);
1500 /***********************************************************************
1501 Glyph display
1502 ***********************************************************************/
1506 static void x_set_glyph_string_clipping (struct glyph_string *);
1507 static void x_set_glyph_string_gc (struct glyph_string *);
1508 static void x_draw_glyph_string_foreground (struct glyph_string *);
1509 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
1510 static void x_draw_glyph_string_box (struct glyph_string *);
1511 static void x_draw_glyph_string (struct glyph_string *);
1512 static _Noreturn void x_delete_glyphs (struct frame *, int);
1513 static void x_compute_glyph_string_overhangs (struct glyph_string *);
1514 static void x_set_cursor_gc (struct glyph_string *);
1515 static void x_set_mode_line_face_gc (struct glyph_string *);
1516 static void x_set_mouse_face_gc (struct glyph_string *);
1517 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
1518 unsigned long *, double, int);
1519 static void x_setup_relief_color (struct frame *, struct relief *,
1520 double, int, unsigned long);
1521 static void x_setup_relief_colors (struct glyph_string *);
1522 static void x_draw_image_glyph_string (struct glyph_string *);
1523 static void x_draw_image_relief (struct glyph_string *);
1524 static void x_draw_image_foreground (struct glyph_string *);
1525 static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
1526 static void x_clear_glyph_string_rect (struct glyph_string *, int,
1527 int, int, int);
1528 static void x_draw_relief_rect (struct frame *, int, int, int, int,
1529 int, bool, bool, bool, bool, bool,
1530 XRectangle *);
1531 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
1532 int, bool, bool, XRectangle *);
1533 static void x_scroll_bar_clear (struct frame *);
1535 #ifdef GLYPH_DEBUG
1536 static void x_check_font (struct frame *, struct font *);
1537 #endif
1540 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1541 face. */
1543 static void
1544 x_set_cursor_gc (struct glyph_string *s)
1546 if (s->font == FRAME_FONT (s->f)
1547 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1548 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1549 && !s->cmp)
1550 s->gc = s->f->output_data.x->cursor_gc;
1551 else
1553 /* Cursor on non-default face: must merge. */
1554 XGCValues xgcv;
1555 unsigned long mask;
1557 xgcv.background = s->f->output_data.x->cursor_pixel;
1558 xgcv.foreground = s->face->background;
1560 /* If the glyph would be invisible, try a different foreground. */
1561 if (xgcv.foreground == xgcv.background)
1562 xgcv.foreground = s->face->foreground;
1563 if (xgcv.foreground == xgcv.background)
1564 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
1565 if (xgcv.foreground == xgcv.background)
1566 xgcv.foreground = s->face->foreground;
1568 /* Make sure the cursor is distinct from text in this face. */
1569 if (xgcv.background == s->face->background
1570 && xgcv.foreground == s->face->foreground)
1572 xgcv.background = s->face->foreground;
1573 xgcv.foreground = s->face->background;
1576 IF_DEBUG (x_check_font (s->f, s->font));
1577 xgcv.graphics_exposures = False;
1578 mask = GCForeground | GCBackground | GCGraphicsExposures;
1580 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1581 XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1582 mask, &xgcv);
1583 else
1584 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1585 = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1587 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1592 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1594 static void
1595 x_set_mouse_face_gc (struct glyph_string *s)
1597 int face_id;
1598 struct face *face;
1600 /* What face has to be used last for the mouse face? */
1601 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1602 face = FACE_FROM_ID_OR_NULL (s->f, face_id);
1603 if (face == NULL)
1604 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1606 if (s->first_glyph->type == CHAR_GLYPH)
1607 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1608 else
1609 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1610 s->face = FACE_FROM_ID (s->f, face_id);
1611 prepare_face_for_display (s->f, s->face);
1613 if (s->font == s->face->font)
1614 s->gc = s->face->gc;
1615 else
1617 /* Otherwise construct scratch_cursor_gc with values from FACE
1618 except for FONT. */
1619 XGCValues xgcv;
1620 unsigned long mask;
1622 xgcv.background = s->face->background;
1623 xgcv.foreground = s->face->foreground;
1624 xgcv.graphics_exposures = False;
1625 mask = GCForeground | GCBackground | GCGraphicsExposures;
1627 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1628 XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1629 mask, &xgcv);
1630 else
1631 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1632 = XCreateGC (s->display, FRAME_X_DRAWABLE (s->f), mask, &xgcv);
1634 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1637 eassert (s->gc != 0);
1641 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1642 Faces to use in the mode line have already been computed when the
1643 matrix was built, so there isn't much to do, here. */
1645 static void
1646 x_set_mode_line_face_gc (struct glyph_string *s)
1648 s->gc = s->face->gc;
1652 /* Set S->gc of glyph string S for drawing that glyph string. Set
1653 S->stippled_p to a non-zero value if the face of S has a stipple
1654 pattern. */
1656 static void
1657 x_set_glyph_string_gc (struct glyph_string *s)
1659 prepare_face_for_display (s->f, s->face);
1661 if (s->hl == DRAW_NORMAL_TEXT)
1663 s->gc = s->face->gc;
1664 s->stippled_p = s->face->stipple != 0;
1666 else if (s->hl == DRAW_INVERSE_VIDEO)
1668 x_set_mode_line_face_gc (s);
1669 s->stippled_p = s->face->stipple != 0;
1671 else if (s->hl == DRAW_CURSOR)
1673 x_set_cursor_gc (s);
1674 s->stippled_p = false;
1676 else if (s->hl == DRAW_MOUSE_FACE)
1678 x_set_mouse_face_gc (s);
1679 s->stippled_p = s->face->stipple != 0;
1681 else if (s->hl == DRAW_IMAGE_RAISED
1682 || s->hl == DRAW_IMAGE_SUNKEN)
1684 s->gc = s->face->gc;
1685 s->stippled_p = s->face->stipple != 0;
1687 else
1688 emacs_abort ();
1690 /* GC must have been set. */
1691 eassert (s->gc != 0);
1695 /* Set clipping for output of glyph string S. S may be part of a mode
1696 line or menu if we don't have X toolkit support. */
1698 static void
1699 x_set_glyph_string_clipping (struct glyph_string *s)
1701 XRectangle *r = s->clip;
1702 int n = get_glyph_string_clip_rects (s, r, 2);
1704 if (n > 0)
1705 x_set_clip_rectangles (s->f, s->gc, r, n);
1706 s->num_clips = n;
1710 /* Set SRC's clipping for output of glyph string DST. This is called
1711 when we are drawing DST's left_overhang or right_overhang only in
1712 the area of SRC. */
1714 static void
1715 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1717 XRectangle r;
1719 r.x = src->x;
1720 r.width = src->width;
1721 r.y = src->y;
1722 r.height = src->height;
1723 dst->clip[0] = r;
1724 dst->num_clips = 1;
1725 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
1729 /* RIF:
1730 Compute left and right overhang of glyph string S. */
1732 static void
1733 x_compute_glyph_string_overhangs (struct glyph_string *s)
1735 if (s->cmp == NULL
1736 && (s->first_glyph->type == CHAR_GLYPH
1737 || s->first_glyph->type == COMPOSITE_GLYPH))
1739 struct font_metrics metrics;
1741 if (s->first_glyph->type == CHAR_GLYPH)
1743 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1744 struct font *font = s->font;
1745 int i;
1747 for (i = 0; i < s->nchars; i++)
1748 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1749 font->driver->text_extents (font, code, s->nchars, &metrics);
1751 else
1753 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1755 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1757 s->right_overhang = (metrics.rbearing > metrics.width
1758 ? metrics.rbearing - metrics.width : 0);
1759 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1761 else if (s->cmp)
1763 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1764 s->left_overhang = - s->cmp->lbearing;
1769 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1771 static void
1772 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1774 XGCValues xgcv;
1775 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1776 XSetForeground (s->display, s->gc, xgcv.background);
1777 x_fill_rectangle (s->f, s->gc, x, y, w, h);
1778 XSetForeground (s->display, s->gc, xgcv.foreground);
1782 /* Draw the background of glyph_string S. If S->background_filled_p
1783 is non-zero don't draw it. FORCE_P non-zero means draw the
1784 background even if it wouldn't be drawn normally. This is used
1785 when a string preceding S draws into the background of S, or S
1786 contains the first component of a composition. */
1788 static void
1789 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1791 /* Nothing to do if background has already been drawn or if it
1792 shouldn't be drawn in the first place. */
1793 if (!s->background_filled_p)
1795 int box_line_width = max (s->face->box_line_width, 0);
1797 if (s->stippled_p)
1799 /* Fill background with a stipple pattern. */
1800 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1801 x_fill_rectangle (s->f, s->gc, s->x,
1802 s->y + box_line_width,
1803 s->background_width,
1804 s->height - 2 * box_line_width);
1805 XSetFillStyle (s->display, s->gc, FillSolid);
1806 s->background_filled_p = true;
1808 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1809 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1810 font dimensions, since the actual glyphs might be
1811 much smaller. So in that case we always clear the
1812 rectangle with background color. */
1813 || FONT_TOO_HIGH (s->font)
1814 || s->font_not_found_p
1815 || s->extends_to_end_of_line_p
1816 || force_p)
1818 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1819 s->background_width,
1820 s->height - 2 * box_line_width);
1821 s->background_filled_p = true;
1827 /* Draw the foreground of glyph string S. */
1829 static void
1830 x_draw_glyph_string_foreground (struct glyph_string *s)
1832 int i, x;
1834 /* If first glyph of S has a left box line, start drawing the text
1835 of S to the right of that box line. */
1836 if (s->face->box != FACE_NO_BOX
1837 && s->first_glyph->left_box_line_p)
1838 x = s->x + eabs (s->face->box_line_width);
1839 else
1840 x = s->x;
1842 /* Draw characters of S as rectangles if S's font could not be
1843 loaded. */
1844 if (s->font_not_found_p)
1846 for (i = 0; i < s->nchars; ++i)
1848 struct glyph *g = s->first_glyph + i;
1849 x_draw_rectangle (s->f,
1850 s->gc, x, s->y, g->pixel_width - 1,
1851 s->height - 1);
1852 x += g->pixel_width;
1855 else
1857 struct font *font = s->font;
1858 int boff = font->baseline_offset;
1859 int y;
1861 if (font->vertical_centering)
1862 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1864 y = s->ybase - boff;
1865 if (s->for_overlaps
1866 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1867 font->driver->draw (s, 0, s->nchars, x, y, false);
1868 else
1869 font->driver->draw (s, 0, s->nchars, x, y, true);
1870 if (s->face->overstrike)
1871 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
1875 /* Draw the foreground of composite glyph string S. */
1877 static void
1878 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1880 int i, j, x;
1881 struct font *font = s->font;
1883 /* If first glyph of S has a left box line, start drawing the text
1884 of S to the right of that box line. */
1885 if (s->face && s->face->box != FACE_NO_BOX
1886 && s->first_glyph->left_box_line_p)
1887 x = s->x + eabs (s->face->box_line_width);
1888 else
1889 x = s->x;
1891 /* S is a glyph string for a composition. S->cmp_from is the index
1892 of the first character drawn for glyphs of this composition.
1893 S->cmp_from == 0 means we are drawing the very first character of
1894 this composition. */
1896 /* Draw a rectangle for the composition if the font for the very
1897 first character of the composition could not be loaded. */
1898 if (s->font_not_found_p)
1900 if (s->cmp_from == 0)
1901 x_draw_rectangle (s->f, s->gc, x, s->y,
1902 s->width - 1, s->height - 1);
1904 else if (! s->first_glyph->u.cmp.automatic)
1906 int y = s->ybase;
1908 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1909 /* TAB in a composition means display glyphs with padding
1910 space on the left or right. */
1911 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1913 int xx = x + s->cmp->offsets[j * 2];
1914 int yy = y - s->cmp->offsets[j * 2 + 1];
1916 font->driver->draw (s, j, j + 1, xx, yy, false);
1917 if (s->face->overstrike)
1918 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1921 else
1923 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1924 Lisp_Object glyph;
1925 int y = s->ybase;
1926 int width = 0;
1928 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1930 glyph = LGSTRING_GLYPH (gstring, i);
1931 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1932 width += LGLYPH_WIDTH (glyph);
1933 else
1935 int xoff, yoff, wadjust;
1937 if (j < i)
1939 font->driver->draw (s, j, i, x, y, false);
1940 if (s->face->overstrike)
1941 font->driver->draw (s, j, i, x + 1, y, false);
1942 x += width;
1944 xoff = LGLYPH_XOFF (glyph);
1945 yoff = LGLYPH_YOFF (glyph);
1946 wadjust = LGLYPH_WADJUST (glyph);
1947 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1948 if (s->face->overstrike)
1949 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1950 false);
1951 x += wadjust;
1952 j = i + 1;
1953 width = 0;
1956 if (j < i)
1958 font->driver->draw (s, j, i, x, y, false);
1959 if (s->face->overstrike)
1960 font->driver->draw (s, j, i, x + 1, y, false);
1966 /* Draw the foreground of glyph string S for glyphless characters. */
1968 static void
1969 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1971 struct glyph *glyph = s->first_glyph;
1972 XChar2b char2b[8];
1973 int x, i, j;
1975 /* If first glyph of S has a left box line, start drawing the text
1976 of S to the right of that box line. */
1977 if (s->face && s->face->box != FACE_NO_BOX
1978 && s->first_glyph->left_box_line_p)
1979 x = s->x + eabs (s->face->box_line_width);
1980 else
1981 x = s->x;
1983 s->char2b = char2b;
1985 for (i = 0; i < s->nchars; i++, glyph++)
1987 char buf[7], *str = NULL;
1988 int len = glyph->u.glyphless.len;
1990 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1992 if (len > 0
1993 && CHAR_TABLE_P (Vglyphless_char_display)
1994 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1995 >= 1))
1997 Lisp_Object acronym
1998 = (! glyph->u.glyphless.for_no_font
1999 ? CHAR_TABLE_REF (Vglyphless_char_display,
2000 glyph->u.glyphless.ch)
2001 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
2002 if (STRINGP (acronym))
2003 str = SSDATA (acronym);
2006 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
2008 sprintf (buf, "%0*X",
2009 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
2010 glyph->u.glyphless.ch + 0u);
2011 str = buf;
2014 if (str)
2016 int upper_len = (len + 1) / 2;
2017 unsigned code;
2019 /* It is assured that all LEN characters in STR is ASCII. */
2020 for (j = 0; j < len; j++)
2022 code = s->font->driver->encode_char (s->font, str[j]);
2023 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
2025 s->font->driver->draw (s, 0, upper_len,
2026 x + glyph->slice.glyphless.upper_xoff,
2027 s->ybase + glyph->slice.glyphless.upper_yoff,
2028 false);
2029 s->font->driver->draw (s, upper_len, len,
2030 x + glyph->slice.glyphless.lower_xoff,
2031 s->ybase + glyph->slice.glyphless.lower_yoff,
2032 false);
2034 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
2035 x_draw_rectangle (s->f, s->gc,
2036 x, s->ybase - glyph->ascent,
2037 glyph->pixel_width - 1,
2038 glyph->ascent + glyph->descent - 1);
2039 x += glyph->pixel_width;
2043 #ifdef USE_X_TOOLKIT
2045 #ifdef USE_LUCID
2047 /* Return the frame on which widget WIDGET is used.. Abort if frame
2048 cannot be determined. */
2050 static struct frame *
2051 x_frame_of_widget (Widget widget)
2053 struct x_display_info *dpyinfo;
2054 Lisp_Object tail, frame;
2055 struct frame *f;
2057 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2059 /* Find the top-level shell of the widget. Note that this function
2060 can be called when the widget is not yet realized, so XtWindow
2061 (widget) == 0. That's the reason we can't simply use
2062 x_any_window_to_frame. */
2063 while (!XtIsTopLevelShell (widget))
2064 widget = XtParent (widget);
2066 /* Look for a frame with that top-level widget. Allocate the color
2067 on that frame to get the right gamma correction value. */
2068 FOR_EACH_FRAME (tail, frame)
2070 f = XFRAME (frame);
2071 if (FRAME_X_P (f)
2072 && f->output_data.nothing != 1
2073 && FRAME_DISPLAY_INFO (f) == dpyinfo
2074 && f->output_data.x->widget == widget)
2075 return f;
2077 emacs_abort ();
2080 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2081 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2082 If this produces the same color as PIXEL, try a color where all RGB
2083 values have DELTA added. Return the allocated color in *PIXEL.
2084 DISPLAY is the X display, CMAP is the colormap to operate on.
2085 Value is true if successful. */
2087 bool
2088 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
2089 unsigned long *pixel, double factor, int delta)
2091 struct frame *f = x_frame_of_widget (widget);
2092 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
2095 #endif /* USE_LUCID */
2098 /* Structure specifying which arguments should be passed by Xt to
2099 cvt_string_to_pixel. We want the widget's screen and colormap. */
2101 static XtConvertArgRec cvt_string_to_pixel_args[] =
2103 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.screen),
2104 sizeof (Screen *)},
2105 {XtWidgetBaseOffset, (XtPointer) offsetof (WidgetRec, core.colormap),
2106 sizeof (Colormap)}
2110 /* The address of this variable is returned by
2111 cvt_string_to_pixel. */
2113 static Pixel cvt_string_to_pixel_value;
2116 /* Convert a color name to a pixel color.
2118 DPY is the display we are working on.
2120 ARGS is an array of *NARGS XrmValue structures holding additional
2121 information about the widget for which the conversion takes place.
2122 The contents of this array are determined by the specification
2123 in cvt_string_to_pixel_args.
2125 FROM is a pointer to an XrmValue which points to the color name to
2126 convert. TO is an XrmValue in which to return the pixel color.
2128 CLOSURE_RET is a pointer to user-data, in which we record if
2129 we allocated the color or not.
2131 Value is True if successful, False otherwise. */
2133 static Boolean
2134 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
2135 XrmValue *from, XrmValue *to,
2136 XtPointer *closure_ret)
2138 Screen *screen;
2139 Colormap cmap;
2140 Pixel pixel;
2141 String color_name;
2142 XColor color;
2144 if (*nargs != 2)
2146 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
2147 "wrongParameters", "cvt_string_to_pixel",
2148 "XtToolkitError",
2149 "Screen and colormap args required", NULL, NULL);
2150 return False;
2153 screen = *(Screen **) args[0].addr;
2154 cmap = *(Colormap *) args[1].addr;
2155 color_name = (String) from->addr;
2157 if (strcmp (color_name, XtDefaultBackground) == 0)
2159 *closure_ret = (XtPointer) False;
2160 pixel = WhitePixelOfScreen (screen);
2162 else if (strcmp (color_name, XtDefaultForeground) == 0)
2164 *closure_ret = (XtPointer) False;
2165 pixel = BlackPixelOfScreen (screen);
2167 else if (XParseColor (dpy, cmap, color_name, &color)
2168 && x_alloc_nearest_color_1 (dpy, cmap, &color))
2170 pixel = color.pixel;
2171 *closure_ret = (XtPointer) True;
2173 else
2175 String params[1];
2176 Cardinal nparams = 1;
2178 params[0] = color_name;
2179 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
2180 "badValue", "cvt_string_to_pixel",
2181 "XtToolkitError", "Invalid color '%s'",
2182 params, &nparams);
2183 return False;
2186 if (to->addr != NULL)
2188 if (to->size < sizeof (Pixel))
2190 to->size = sizeof (Pixel);
2191 return False;
2194 *(Pixel *) to->addr = pixel;
2196 else
2198 cvt_string_to_pixel_value = pixel;
2199 to->addr = (XtPointer) &cvt_string_to_pixel_value;
2202 to->size = sizeof (Pixel);
2203 return True;
2207 /* Free a pixel color which was previously allocated via
2208 cvt_string_to_pixel. This is registered as the destructor
2209 for this type of resource via XtSetTypeConverter.
2211 APP is the application context in which we work.
2213 TO is a pointer to an XrmValue holding the color to free.
2214 CLOSURE is the value we stored in CLOSURE_RET for this color
2215 in cvt_string_to_pixel.
2217 ARGS and NARGS are like for cvt_string_to_pixel. */
2219 static void
2220 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
2221 Cardinal *nargs)
2223 if (*nargs != 2)
2225 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
2226 "XtToolkitError",
2227 "Screen and colormap arguments required",
2228 NULL, NULL);
2230 else if (closure != NULL)
2232 /* We did allocate the pixel, so free it. */
2233 Screen *screen = *(Screen **) args[0].addr;
2234 Colormap cmap = *(Colormap *) args[1].addr;
2235 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
2236 (Pixel *) to->addr, 1);
2241 #endif /* USE_X_TOOLKIT */
2244 /* Value is an array of XColor structures for the contents of the
2245 color map of display DPY. Set *NCELLS to the size of the array.
2246 Note that this probably shouldn't be called for large color maps,
2247 say a 24-bit TrueColor map. */
2249 static const XColor *
2250 x_color_cells (Display *dpy, int *ncells)
2252 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
2253 eassume (dpyinfo);
2255 if (dpyinfo->color_cells == NULL)
2257 Screen *screen = dpyinfo->screen;
2258 int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
2259 int i;
2261 dpyinfo->color_cells = xnmalloc (ncolor_cells,
2262 sizeof *dpyinfo->color_cells);
2263 dpyinfo->ncolor_cells = ncolor_cells;
2265 for (i = 0; i < ncolor_cells; ++i)
2266 dpyinfo->color_cells[i].pixel = i;
2268 XQueryColors (dpy, dpyinfo->cmap,
2269 dpyinfo->color_cells, ncolor_cells);
2272 *ncells = dpyinfo->ncolor_cells;
2273 return dpyinfo->color_cells;
2277 /* On frame F, translate pixel colors to RGB values for the NCOLORS
2278 colors in COLORS. Use cached information, if available. */
2280 void
2281 x_query_colors (struct frame *f, XColor *colors, int ncolors)
2283 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2285 if (dpyinfo->red_bits > 0)
2287 /* For TrueColor displays, we can decompose the RGB value
2288 directly. */
2289 int i;
2290 unsigned int rmult, gmult, bmult;
2291 unsigned int rmask, gmask, bmask;
2293 rmask = (1 << dpyinfo->red_bits) - 1;
2294 gmask = (1 << dpyinfo->green_bits) - 1;
2295 bmask = (1 << dpyinfo->blue_bits) - 1;
2296 /* If we're widening, for example, 8 bits in the pixel value to
2297 16 bits for the separate-color representation, we want to
2298 extrapolate the lower bits based on those bits available --
2299 in other words, we'd like 0xff to become 0xffff instead of
2300 the 0xff00 we'd get by just zero-filling the lower bits.
2302 We generate a 32-bit scaled-up value and shift it, in case
2303 the bit count doesn't divide 16 evenly (e.g., when dealing
2304 with a 3-3-2 bit RGB display), to get more of the lower bits
2305 correct.
2307 Should we cache the multipliers in dpyinfo? Maybe
2308 special-case the 8-8-8 common case? */
2309 rmult = 0xffffffff / rmask;
2310 gmult = 0xffffffff / gmask;
2311 bmult = 0xffffffff / bmask;
2313 for (i = 0; i < ncolors; ++i)
2315 unsigned int r, g, b;
2316 unsigned long pixel = colors[i].pixel;
2318 r = (pixel >> dpyinfo->red_offset) & rmask;
2319 g = (pixel >> dpyinfo->green_offset) & gmask;
2320 b = (pixel >> dpyinfo->blue_offset) & bmask;
2322 colors[i].red = (r * rmult) >> 16;
2323 colors[i].green = (g * gmult) >> 16;
2324 colors[i].blue = (b * bmult) >> 16;
2326 return;
2329 if (dpyinfo->color_cells)
2331 int i;
2332 for (i = 0; i < ncolors; ++i)
2334 unsigned long pixel = colors[i].pixel;
2335 eassert (pixel < dpyinfo->ncolor_cells);
2336 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
2337 colors[i] = dpyinfo->color_cells[pixel];
2339 return;
2342 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
2346 /* On frame F, translate pixel color to RGB values for the color in
2347 COLOR. Use cached information, if available. */
2349 void
2350 x_query_color (struct frame *f, XColor *color)
2352 x_query_colors (f, color, 1);
2356 /* On frame F, translate the color name to RGB values. Use cached
2357 information, if possible.
2359 Note that there is currently no way to clean old entries out of the
2360 cache. However, it is limited to names in the server's database,
2361 and names we've actually looked up; list-colors-display is probably
2362 the most color-intensive case we're likely to hit. */
2364 Status x_parse_color (struct frame *f, const char *color_name,
2365 XColor *color)
2367 Display *dpy = FRAME_X_DISPLAY (f);
2368 Colormap cmap = FRAME_X_COLORMAP (f);
2369 struct color_name_cache_entry *cache_entry;
2371 if (color_name[0] == '#')
2373 /* The hex form is parsed directly by XParseColor without
2374 talking to the X server. No need for caching. */
2375 return XParseColor (dpy, cmap, color_name, color);
2378 for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry;
2379 cache_entry = cache_entry->next)
2381 if (!xstrcasecmp(cache_entry->name, color_name))
2383 *color = cache_entry->rgb;
2384 return 1;
2388 if (XParseColor (dpy, cmap, color_name, color) == 0)
2389 /* No caching of negative results, currently. */
2390 return 0;
2392 cache_entry = xzalloc (sizeof *cache_entry);
2393 cache_entry->rgb = *color;
2394 cache_entry->name = xstrdup (color_name);
2395 cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names;
2396 FRAME_DISPLAY_INFO (f)->color_names = cache_entry;
2397 return 1;
2401 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
2402 exact match can't be allocated, try the nearest color available.
2403 Value is true if successful. Set *COLOR to the color
2404 allocated. */
2406 static bool
2407 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
2409 bool rc;
2411 rc = XAllocColor (dpy, cmap, color) != 0;
2412 if (rc == 0)
2414 /* If we got to this point, the colormap is full, so we're going
2415 to try to get the next closest color. The algorithm used is
2416 a least-squares matching, which is what X uses for closest
2417 color matching with StaticColor visuals. */
2418 int nearest, i;
2419 int max_color_delta = 255;
2420 int max_delta = 3 * max_color_delta;
2421 int nearest_delta = max_delta + 1;
2422 int ncells;
2423 const XColor *cells = x_color_cells (dpy, &ncells);
2425 for (nearest = i = 0; i < ncells; ++i)
2427 int dred = (color->red >> 8) - (cells[i].red >> 8);
2428 int dgreen = (color->green >> 8) - (cells[i].green >> 8);
2429 int dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2430 int delta = dred * dred + dgreen * dgreen + dblue * dblue;
2432 if (delta < nearest_delta)
2434 nearest = i;
2435 nearest_delta = delta;
2439 color->red = cells[nearest].red;
2440 color->green = cells[nearest].green;
2441 color->blue = cells[nearest].blue;
2442 rc = XAllocColor (dpy, cmap, color) != 0;
2444 else
2446 /* If allocation succeeded, and the allocated pixel color is not
2447 equal to a cached pixel color recorded earlier, there was a
2448 change in the colormap, so clear the color cache. */
2449 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
2450 eassume (dpyinfo);
2452 if (dpyinfo->color_cells)
2454 XColor *cached_color = &dpyinfo->color_cells[color->pixel];
2455 if (cached_color->red != color->red
2456 || cached_color->blue != color->blue
2457 || cached_color->green != color->green)
2459 xfree (dpyinfo->color_cells);
2460 dpyinfo->color_cells = NULL;
2461 dpyinfo->ncolor_cells = 0;
2466 #ifdef DEBUG_X_COLORS
2467 if (rc)
2468 register_color (color->pixel);
2469 #endif /* DEBUG_X_COLORS */
2471 return rc;
2475 /* Allocate the color COLOR->pixel on frame F, colormap CMAP, after
2476 gamma correction. If an exact match can't be allocated, try the
2477 nearest color available. Value is true if successful. Set *COLOR
2478 to the color allocated. */
2480 bool
2481 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
2483 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2485 gamma_correct (f, color);
2487 if (dpyinfo->red_bits > 0)
2489 color->pixel = x_make_truecolor_pixel (dpyinfo,
2490 color->red,
2491 color->green,
2492 color->blue);
2493 return true;
2496 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
2500 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2501 It's necessary to do this instead of just using PIXEL directly to
2502 get color reference counts right. */
2504 unsigned long
2505 x_copy_color (struct frame *f, unsigned long pixel)
2507 XColor color;
2509 /* If display has an immutable color map, freeing colors is not
2510 necessary and some servers don't allow it. Since we won't free a
2511 color once we've allocated it, we don't need to re-allocate it to
2512 maintain the server's reference count. */
2513 if (!x_mutable_colormap (FRAME_X_VISUAL (f)))
2514 return pixel;
2516 color.pixel = pixel;
2517 block_input ();
2518 /* The color could still be found in the color_cells array. */
2519 x_query_color (f, &color);
2520 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2521 unblock_input ();
2522 #ifdef DEBUG_X_COLORS
2523 register_color (pixel);
2524 #endif
2525 return color.pixel;
2529 /* Brightness beyond which a color won't have its highlight brightness
2530 boosted.
2532 Nominally, highlight colors for `3d' faces are calculated by
2533 brightening an object's color by a constant scale factor, but this
2534 doesn't yield good results for dark colors, so for colors who's
2535 brightness is less than this value (on a scale of 0-65535) have an
2536 use an additional additive factor.
2538 The value here is set so that the default menu-bar/mode-line color
2539 (grey75) will not have its highlights changed at all. */
2540 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
2543 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2544 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2545 If this produces the same color as PIXEL, try a color where all RGB
2546 values have DELTA added. Return the allocated color in *PIXEL.
2547 DISPLAY is the X display, CMAP is the colormap to operate on.
2548 Value is non-zero if successful. */
2550 static bool
2551 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
2552 unsigned long *pixel, double factor, int delta)
2554 XColor color, new;
2555 long bright;
2556 bool success_p;
2558 /* Get RGB color values. */
2559 color.pixel = *pixel;
2560 x_query_color (f, &color);
2562 /* Change RGB values by specified FACTOR. Avoid overflow! */
2563 eassert (factor >= 0);
2564 new.red = min (0xffff, factor * color.red);
2565 new.green = min (0xffff, factor * color.green);
2566 new.blue = min (0xffff, factor * color.blue);
2568 /* Calculate brightness of COLOR. */
2569 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
2571 /* We only boost colors that are darker than
2572 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2573 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2574 /* Make an additive adjustment to NEW, because it's dark enough so
2575 that scaling by FACTOR alone isn't enough. */
2577 /* How far below the limit this color is (0 - 1, 1 being darker). */
2578 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2579 /* The additive adjustment. */
2580 int min_delta = delta * dimness * factor / 2;
2582 if (factor < 1)
2584 new.red = max (0, new.red - min_delta);
2585 new.green = max (0, new.green - min_delta);
2586 new.blue = max (0, new.blue - min_delta);
2588 else
2590 new.red = min (0xffff, min_delta + new.red);
2591 new.green = min (0xffff, min_delta + new.green);
2592 new.blue = min (0xffff, min_delta + new.blue);
2596 /* Try to allocate the color. */
2597 success_p = x_alloc_nearest_color (f, cmap, &new);
2598 if (success_p)
2600 if (new.pixel == *pixel)
2602 /* If we end up with the same color as before, try adding
2603 delta to the RGB values. */
2604 x_free_colors (f, &new.pixel, 1);
2606 new.red = min (0xffff, delta + color.red);
2607 new.green = min (0xffff, delta + color.green);
2608 new.blue = min (0xffff, delta + color.blue);
2609 success_p = x_alloc_nearest_color (f, cmap, &new);
2611 else
2612 success_p = true;
2613 *pixel = new.pixel;
2616 return success_p;
2620 /* Set up the foreground color for drawing relief lines of glyph
2621 string S. RELIEF is a pointer to a struct relief containing the GC
2622 with which lines will be drawn. Use a color that is FACTOR or
2623 DELTA lighter or darker than the relief's background which is found
2624 in S->f->output_data.x->relief_background. If such a color cannot
2625 be allocated, use DEFAULT_PIXEL, instead. */
2627 static void
2628 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
2629 int delta, unsigned long default_pixel)
2631 XGCValues xgcv;
2632 struct x_output *di = f->output_data.x;
2633 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
2634 unsigned long pixel;
2635 unsigned long background = di->relief_background;
2636 Colormap cmap = FRAME_X_COLORMAP (f);
2637 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2638 Display *dpy = FRAME_X_DISPLAY (f);
2640 xgcv.graphics_exposures = False;
2641 xgcv.line_width = 1;
2643 /* Free previously allocated color. The color cell will be reused
2644 when it has been freed as many times as it was allocated, so this
2645 doesn't affect faces using the same colors. */
2646 if (relief->gc && relief->pixel != -1)
2648 x_free_colors (f, &relief->pixel, 1);
2649 relief->pixel = -1;
2652 /* Allocate new color. */
2653 xgcv.foreground = default_pixel;
2654 pixel = background;
2655 if (dpyinfo->n_planes != 1
2656 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
2657 xgcv.foreground = relief->pixel = pixel;
2659 if (relief->gc == 0)
2661 xgcv.stipple = dpyinfo->gray;
2662 mask |= GCStipple;
2663 relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
2665 else
2666 XChangeGC (dpy, relief->gc, mask, &xgcv);
2670 /* Set up colors for the relief lines around glyph string S. */
2672 static void
2673 x_setup_relief_colors (struct glyph_string *s)
2675 struct x_output *di = s->f->output_data.x;
2676 unsigned long color;
2678 if (s->face->use_box_color_for_shadows_p)
2679 color = s->face->box_color;
2680 else if (s->first_glyph->type == IMAGE_GLYPH
2681 && s->img->pixmap
2682 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2683 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2684 else
2686 XGCValues xgcv;
2688 /* Get the background color of the face. */
2689 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2690 color = xgcv.background;
2693 if (di->white_relief.gc == 0
2694 || color != di->relief_background)
2696 di->relief_background = color;
2697 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2698 WHITE_PIX_DEFAULT (s->f));
2699 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2700 BLACK_PIX_DEFAULT (s->f));
2705 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2706 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2707 to draw, it must be >= 0. RAISED_P means draw a raised
2708 relief. LEFT_P means draw a relief on the left side of
2709 the rectangle. RIGHT_P means draw a relief on the right
2710 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2711 when drawing. */
2713 static void
2714 x_draw_relief_rect (struct frame *f,
2715 int left_x, int top_y, int right_x, int bottom_y,
2716 int width, bool raised_p, bool top_p, bool bot_p,
2717 bool left_p, bool right_p,
2718 XRectangle *clip_rect)
2720 #ifdef USE_CAIRO
2721 GC top_left_gc, bottom_right_gc;
2722 int corners = 0;
2724 if (raised_p)
2726 top_left_gc = f->output_data.x->white_relief.gc;
2727 bottom_right_gc = f->output_data.x->black_relief.gc;
2729 else
2731 top_left_gc = f->output_data.x->black_relief.gc;
2732 bottom_right_gc = f->output_data.x->white_relief.gc;
2735 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
2736 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
2738 if (left_p)
2740 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2741 width, bottom_y + 1 - top_y);
2742 if (top_p)
2743 corners |= 1 << CORNER_TOP_LEFT;
2744 if (bot_p)
2745 corners |= 1 << CORNER_BOTTOM_LEFT;
2747 if (right_p)
2749 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
2750 width, bottom_y + 1 - top_y);
2751 if (top_p)
2752 corners |= 1 << CORNER_TOP_RIGHT;
2753 if (bot_p)
2754 corners |= 1 << CORNER_BOTTOM_RIGHT;
2756 if (top_p)
2758 if (!right_p)
2759 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2760 right_x + 1 - left_x, width);
2761 else
2762 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
2763 right_x + 1 - left_x, width, 1);
2765 if (bot_p)
2767 if (!left_p)
2768 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
2769 right_x + 1 - left_x, width);
2770 else
2771 x_fill_trapezoid_for_relief (f, bottom_right_gc,
2772 left_x, bottom_y + 1 - width,
2773 right_x + 1 - left_x, width, 0);
2775 if (left_p && width != 1)
2776 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2777 1, bottom_y + 1 - top_y);
2778 if (top_p && width != 1)
2779 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2780 right_x + 1 - left_x, 1);
2781 if (corners)
2783 XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
2784 FRAME_BACKGROUND_PIXEL (f));
2785 x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
2786 right_x - left_x + 1, bottom_y - top_y + 1,
2787 6, 1, corners);
2790 x_reset_clip_rectangles (f, top_left_gc);
2791 x_reset_clip_rectangles (f, bottom_right_gc);
2792 #else
2793 Display *dpy = FRAME_X_DISPLAY (f);
2794 Drawable drawable = FRAME_X_DRAWABLE (f);
2795 int i;
2796 GC gc;
2798 if (raised_p)
2799 gc = f->output_data.x->white_relief.gc;
2800 else
2801 gc = f->output_data.x->black_relief.gc;
2802 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2804 /* This code is more complicated than it has to be, because of two
2805 minor hacks to make the boxes look nicer: (i) if width > 1, draw
2806 the outermost line using the black relief. (ii) Omit the four
2807 corner pixels. */
2809 /* Top. */
2810 if (top_p)
2812 if (width == 1)
2813 XDrawLine (dpy, drawable, gc,
2814 left_x + left_p, top_y,
2815 right_x + !right_p, top_y);
2817 for (i = 1; i < width; ++i)
2818 XDrawLine (dpy, drawable, gc,
2819 left_x + i * left_p, top_y + i,
2820 right_x + 1 - i * right_p, top_y + i);
2823 /* Left. */
2824 if (left_p)
2826 if (width == 1)
2827 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2829 x_clear_area(f, left_x, top_y, 1, 1);
2830 x_clear_area(f, left_x, bottom_y, 1, 1);
2832 for (i = (width > 1 ? 1 : 0); i < width; ++i)
2833 XDrawLine (dpy, drawable, gc,
2834 left_x + i, top_y + (i + 1) * top_p,
2835 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
2838 XSetClipMask (dpy, gc, None);
2839 if (raised_p)
2840 gc = f->output_data.x->black_relief.gc;
2841 else
2842 gc = f->output_data.x->white_relief.gc;
2843 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2845 if (width > 1)
2847 /* Outermost top line. */
2848 if (top_p)
2849 XDrawLine (dpy, drawable, gc,
2850 left_x + left_p, top_y,
2851 right_x + !right_p, top_y);
2853 /* Outermost left line. */
2854 if (left_p)
2855 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2858 /* Bottom. */
2859 if (bot_p)
2861 XDrawLine (dpy, drawable, gc,
2862 left_x + left_p, bottom_y,
2863 right_x + !right_p, bottom_y);
2864 for (i = 1; i < width; ++i)
2865 XDrawLine (dpy, drawable, gc,
2866 left_x + i * left_p, bottom_y - i,
2867 right_x + 1 - i * right_p, bottom_y - i);
2870 /* Right. */
2871 if (right_p)
2873 x_clear_area(f, right_x, top_y, 1, 1);
2874 x_clear_area(f, right_x, bottom_y, 1, 1);
2875 for (i = 0; i < width; ++i)
2876 XDrawLine (dpy, drawable, gc,
2877 right_x - i, top_y + (i + 1) * top_p,
2878 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
2881 x_reset_clip_rectangles (f, gc);
2883 #endif
2887 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2888 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2889 draw, it must be >= 0. LEFT_P means draw a line on the
2890 left side of the rectangle. RIGHT_P means draw a line
2891 on the right side of the rectangle. CLIP_RECT is the clipping
2892 rectangle to use when drawing. */
2894 static void
2895 x_draw_box_rect (struct glyph_string *s,
2896 int left_x, int top_y, int right_x, int bottom_y, int width,
2897 bool left_p, bool right_p, XRectangle *clip_rect)
2899 XGCValues xgcv;
2901 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2902 XSetForeground (s->display, s->gc, s->face->box_color);
2903 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
2905 /* Top. */
2906 x_fill_rectangle (s->f, s->gc,
2907 left_x, top_y, right_x - left_x + 1, width);
2909 /* Left. */
2910 if (left_p)
2911 x_fill_rectangle (s->f, s->gc,
2912 left_x, top_y, width, bottom_y - top_y + 1);
2914 /* Bottom. */
2915 x_fill_rectangle (s->f, s->gc,
2916 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2918 /* Right. */
2919 if (right_p)
2920 x_fill_rectangle (s->f, s->gc,
2921 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2923 XSetForeground (s->display, s->gc, xgcv.foreground);
2924 x_reset_clip_rectangles (s->f, s->gc);
2928 /* Draw a box around glyph string S. */
2930 static void
2931 x_draw_glyph_string_box (struct glyph_string *s)
2933 int width, left_x, right_x, top_y, bottom_y, last_x;
2934 bool raised_p, left_p, right_p;
2935 struct glyph *last_glyph;
2936 XRectangle clip_rect;
2938 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2939 ? WINDOW_RIGHT_EDGE_X (s->w)
2940 : window_box_right (s->w, s->area));
2942 /* The glyph that may have a right box line. */
2943 last_glyph = (s->cmp || s->img
2944 ? s->first_glyph
2945 : s->first_glyph + s->nchars - 1);
2947 width = eabs (s->face->box_line_width);
2948 raised_p = s->face->box == FACE_RAISED_BOX;
2949 left_x = s->x;
2950 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2951 ? last_x - 1
2952 : min (last_x, s->x + s->background_width) - 1);
2953 top_y = s->y;
2954 bottom_y = top_y + s->height - 1;
2956 left_p = (s->first_glyph->left_box_line_p
2957 || (s->hl == DRAW_MOUSE_FACE
2958 && (s->prev == NULL
2959 || s->prev->hl != s->hl)));
2960 right_p = (last_glyph->right_box_line_p
2961 || (s->hl == DRAW_MOUSE_FACE
2962 && (s->next == NULL
2963 || s->next->hl != s->hl)));
2965 get_glyph_string_clip_rect (s, &clip_rect);
2967 if (s->face->box == FACE_SIMPLE_BOX)
2968 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2969 left_p, right_p, &clip_rect);
2970 else
2972 x_setup_relief_colors (s);
2973 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2974 width, raised_p, true, true, left_p, right_p,
2975 &clip_rect);
2980 /* Draw foreground of image glyph string S. */
2982 static void
2983 x_draw_image_foreground (struct glyph_string *s)
2985 int x = s->x;
2986 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2988 /* If first glyph of S has a left box line, start drawing it to the
2989 right of that line. */
2990 if (s->face->box != FACE_NO_BOX
2991 && s->first_glyph->left_box_line_p
2992 && s->slice.x == 0)
2993 x += eabs (s->face->box_line_width);
2995 /* If there is a margin around the image, adjust x- and y-position
2996 by that margin. */
2997 if (s->slice.x == 0)
2998 x += s->img->hmargin;
2999 if (s->slice.y == 0)
3000 y += s->img->vmargin;
3002 if (s->img->pixmap)
3004 if (s->img->mask)
3006 /* We can't set both a clip mask and use XSetClipRectangles
3007 because the latter also sets a clip mask. We also can't
3008 trust on the shape extension to be available
3009 (XShapeCombineRegion). So, compute the rectangle to draw
3010 manually. */
3011 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3012 | GCFunction);
3013 XGCValues xgcv;
3014 XRectangle clip_rect, image_rect, r;
3016 xgcv.clip_mask = s->img->mask;
3017 xgcv.clip_x_origin = x;
3018 xgcv.clip_y_origin = y;
3019 xgcv.function = GXcopy;
3020 XChangeGC (s->display, s->gc, mask, &xgcv);
3022 get_glyph_string_clip_rect (s, &clip_rect);
3023 image_rect.x = x;
3024 image_rect.y = y;
3025 image_rect.width = s->slice.width;
3026 image_rect.height = s->slice.height;
3027 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3028 XCopyArea (s->display, s->img->pixmap,
3029 FRAME_X_DRAWABLE (s->f), s->gc,
3030 s->slice.x + r.x - x, s->slice.y + r.y - y,
3031 r.width, r.height, r.x, r.y);
3033 else
3035 XRectangle clip_rect, image_rect, r;
3037 get_glyph_string_clip_rect (s, &clip_rect);
3038 image_rect.x = x;
3039 image_rect.y = y;
3040 image_rect.width = s->slice.width;
3041 image_rect.height = s->slice.height;
3042 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3043 XCopyArea (s->display, s->img->pixmap,
3044 FRAME_X_DRAWABLE (s->f), s->gc,
3045 s->slice.x + r.x - x, s->slice.y + r.y - y,
3046 r.width, r.height, r.x, r.y);
3048 /* When the image has a mask, we can expect that at
3049 least part of a mouse highlight or a block cursor will
3050 be visible. If the image doesn't have a mask, make
3051 a block cursor visible by drawing a rectangle around
3052 the image. I believe it's looking better if we do
3053 nothing here for mouse-face. */
3054 if (s->hl == DRAW_CURSOR)
3056 int relief = eabs (s->img->relief);
3057 x_draw_rectangle (s->f, s->gc,
3058 x - relief, y - relief,
3059 s->slice.width + relief*2 - 1,
3060 s->slice.height + relief*2 - 1);
3064 else
3065 /* Draw a rectangle if image could not be loaded. */
3066 x_draw_rectangle (s->f, s->gc, x, y,
3067 s->slice.width - 1, s->slice.height - 1);
3071 /* Draw a relief around the image glyph string S. */
3073 static void
3074 x_draw_image_relief (struct glyph_string *s)
3076 int x1, y1, thick;
3077 bool raised_p, top_p, bot_p, left_p, right_p;
3078 int extra_x, extra_y;
3079 XRectangle r;
3080 int x = s->x;
3081 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3083 /* If first glyph of S has a left box line, start drawing it to the
3084 right of that line. */
3085 if (s->face->box != FACE_NO_BOX
3086 && s->first_glyph->left_box_line_p
3087 && s->slice.x == 0)
3088 x += eabs (s->face->box_line_width);
3090 /* If there is a margin around the image, adjust x- and y-position
3091 by that margin. */
3092 if (s->slice.x == 0)
3093 x += s->img->hmargin;
3094 if (s->slice.y == 0)
3095 y += s->img->vmargin;
3097 if (s->hl == DRAW_IMAGE_SUNKEN
3098 || s->hl == DRAW_IMAGE_RAISED)
3100 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3101 raised_p = s->hl == DRAW_IMAGE_RAISED;
3103 else
3105 thick = eabs (s->img->relief);
3106 raised_p = s->img->relief > 0;
3109 x1 = x + s->slice.width - 1;
3110 y1 = y + s->slice.height - 1;
3112 extra_x = extra_y = 0;
3113 if (s->face->id == TOOL_BAR_FACE_ID)
3115 if (CONSP (Vtool_bar_button_margin)
3116 && INTEGERP (XCAR (Vtool_bar_button_margin))
3117 && INTEGERP (XCDR (Vtool_bar_button_margin)))
3119 extra_x = XINT (XCAR (Vtool_bar_button_margin));
3120 extra_y = XINT (XCDR (Vtool_bar_button_margin));
3122 else if (INTEGERP (Vtool_bar_button_margin))
3123 extra_x = extra_y = XINT (Vtool_bar_button_margin);
3126 top_p = bot_p = left_p = right_p = false;
3128 if (s->slice.x == 0)
3129 x -= thick + extra_x, left_p = true;
3130 if (s->slice.y == 0)
3131 y -= thick + extra_y, top_p = true;
3132 if (s->slice.x + s->slice.width == s->img->width)
3133 x1 += thick + extra_x, right_p = true;
3134 if (s->slice.y + s->slice.height == s->img->height)
3135 y1 += thick + extra_y, bot_p = true;
3137 x_setup_relief_colors (s);
3138 get_glyph_string_clip_rect (s, &r);
3139 x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
3140 top_p, bot_p, left_p, right_p, &r);
3144 /* Draw the foreground of image glyph string S to PIXMAP. */
3146 static void
3147 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
3149 int x = 0;
3150 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
3152 /* If first glyph of S has a left box line, start drawing it to the
3153 right of that line. */
3154 if (s->face->box != FACE_NO_BOX
3155 && s->first_glyph->left_box_line_p
3156 && s->slice.x == 0)
3157 x += eabs (s->face->box_line_width);
3159 /* If there is a margin around the image, adjust x- and y-position
3160 by that margin. */
3161 if (s->slice.x == 0)
3162 x += s->img->hmargin;
3163 if (s->slice.y == 0)
3164 y += s->img->vmargin;
3166 if (s->img->pixmap)
3168 if (s->img->mask)
3170 /* We can't set both a clip mask and use XSetClipRectangles
3171 because the latter also sets a clip mask. We also can't
3172 trust on the shape extension to be available
3173 (XShapeCombineRegion). So, compute the rectangle to draw
3174 manually. */
3175 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3176 | GCFunction);
3177 XGCValues xgcv;
3179 xgcv.clip_mask = s->img->mask;
3180 xgcv.clip_x_origin = x - s->slice.x;
3181 xgcv.clip_y_origin = y - s->slice.y;
3182 xgcv.function = GXcopy;
3183 XChangeGC (s->display, s->gc, mask, &xgcv);
3185 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3186 s->slice.x, s->slice.y,
3187 s->slice.width, s->slice.height, x, y);
3188 XSetClipMask (s->display, s->gc, None);
3190 else
3192 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3193 s->slice.x, s->slice.y,
3194 s->slice.width, s->slice.height, x, y);
3196 /* When the image has a mask, we can expect that at
3197 least part of a mouse highlight or a block cursor will
3198 be visible. If the image doesn't have a mask, make
3199 a block cursor visible by drawing a rectangle around
3200 the image. I believe it's looking better if we do
3201 nothing here for mouse-face. */
3202 if (s->hl == DRAW_CURSOR)
3204 int r = eabs (s->img->relief);
3205 x_draw_rectangle (s->f, s->gc, x - r, y - r,
3206 s->slice.width + r*2 - 1,
3207 s->slice.height + r*2 - 1);
3211 else
3212 /* Draw a rectangle if image could not be loaded. */
3213 x_draw_rectangle (s->f, s->gc, x, y,
3214 s->slice.width - 1, s->slice.height - 1);
3218 /* Draw part of the background of glyph string S. X, Y, W, and H
3219 give the rectangle to draw. */
3221 static void
3222 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
3224 if (s->stippled_p)
3226 /* Fill background with a stipple pattern. */
3227 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3228 x_fill_rectangle (s->f, s->gc, x, y, w, h);
3229 XSetFillStyle (s->display, s->gc, FillSolid);
3231 else
3232 x_clear_glyph_string_rect (s, x, y, w, h);
3236 /* Draw image glyph string S.
3238 s->y
3239 s->x +-------------------------
3240 | s->face->box
3242 | +-------------------------
3243 | | s->img->margin
3245 | | +-------------------
3246 | | | the image
3250 static void
3251 x_draw_image_glyph_string (struct glyph_string *s)
3253 int box_line_hwidth = eabs (s->face->box_line_width);
3254 int box_line_vwidth = max (s->face->box_line_width, 0);
3255 int height;
3256 Pixmap pixmap = None;
3258 height = s->height;
3259 if (s->slice.y == 0)
3260 height -= box_line_vwidth;
3261 if (s->slice.y + s->slice.height >= s->img->height)
3262 height -= box_line_vwidth;
3264 /* Fill background with face under the image. Do it only if row is
3265 taller than image or if image has a clip mask to reduce
3266 flickering. */
3267 s->stippled_p = s->face->stipple != 0;
3268 if (height > s->slice.height
3269 || s->img->hmargin
3270 || s->img->vmargin
3271 || s->img->mask
3272 || s->img->pixmap == 0
3273 || s->width != s->background_width)
3275 if (s->img->mask)
3277 /* Create a pixmap as large as the glyph string. Fill it
3278 with the background color. Copy the image to it, using
3279 its mask. Copy the temporary pixmap to the display. */
3280 Screen *screen = FRAME_X_SCREEN (s->f);
3281 int depth = DefaultDepthOfScreen (screen);
3283 /* Create a pixmap as large as the glyph string. */
3284 pixmap = XCreatePixmap (s->display, FRAME_X_DRAWABLE (s->f),
3285 s->background_width,
3286 s->height, depth);
3288 /* Don't clip in the following because we're working on the
3289 pixmap. */
3290 XSetClipMask (s->display, s->gc, None);
3292 /* Fill the pixmap with the background color/stipple. */
3293 if (s->stippled_p)
3295 /* Fill background with a stipple pattern. */
3296 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3297 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
3298 XFillRectangle (s->display, pixmap, s->gc,
3299 0, 0, s->background_width, s->height);
3300 XSetFillStyle (s->display, s->gc, FillSolid);
3301 XSetTSOrigin (s->display, s->gc, 0, 0);
3303 else
3305 XGCValues xgcv;
3306 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3307 &xgcv);
3308 XSetForeground (s->display, s->gc, xgcv.background);
3309 XFillRectangle (s->display, pixmap, s->gc,
3310 0, 0, s->background_width, s->height);
3311 XSetForeground (s->display, s->gc, xgcv.foreground);
3314 else
3316 int x = s->x;
3317 int y = s->y;
3318 int width = s->background_width;
3320 if (s->first_glyph->left_box_line_p
3321 && s->slice.x == 0)
3323 x += box_line_hwidth;
3324 width -= box_line_hwidth;
3327 if (s->slice.y == 0)
3328 y += box_line_vwidth;
3330 x_draw_glyph_string_bg_rect (s, x, y, width, height);
3333 s->background_filled_p = true;
3336 /* Draw the foreground. */
3337 #ifdef USE_CAIRO
3338 if (s->img->cr_data)
3340 cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
3342 int x = s->x + s->img->hmargin;
3343 int y = s->y + s->img->vmargin;
3344 int width = s->background_width;
3346 cairo_set_source_surface (cr, s->img->cr_data,
3347 x - s->slice.x,
3348 y - s->slice.y);
3349 cairo_rectangle (cr, x, y, width, height);
3350 cairo_fill (cr);
3351 x_end_cr_clip (s->f);
3353 else
3354 #endif
3355 if (pixmap != None)
3357 x_draw_image_foreground_1 (s, pixmap);
3358 x_set_glyph_string_clipping (s);
3359 XCopyArea (s->display, pixmap, FRAME_X_DRAWABLE (s->f), s->gc,
3360 0, 0, s->background_width, s->height, s->x, s->y);
3361 XFreePixmap (s->display, pixmap);
3363 else
3364 x_draw_image_foreground (s);
3366 /* If we must draw a relief around the image, do it. */
3367 if (s->img->relief
3368 || s->hl == DRAW_IMAGE_RAISED
3369 || s->hl == DRAW_IMAGE_SUNKEN)
3370 x_draw_image_relief (s);
3374 /* Draw stretch glyph string S. */
3376 static void
3377 x_draw_stretch_glyph_string (struct glyph_string *s)
3379 eassert (s->first_glyph->type == STRETCH_GLYPH);
3381 if (s->hl == DRAW_CURSOR
3382 && !x_stretch_cursor_p)
3384 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
3385 wide as the stretch glyph. */
3386 int width, background_width = s->background_width;
3387 int x = s->x;
3389 if (!s->row->reversed_p)
3391 int left_x = window_box_left_offset (s->w, TEXT_AREA);
3393 if (x < left_x)
3395 background_width -= left_x - x;
3396 x = left_x;
3399 else
3401 /* In R2L rows, draw the cursor on the right edge of the
3402 stretch glyph. */
3403 int right_x = window_box_right (s->w, TEXT_AREA);
3405 if (x + background_width > right_x)
3406 background_width -= x - right_x;
3407 x += background_width;
3409 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3410 if (s->row->reversed_p)
3411 x -= width;
3413 /* Draw cursor. */
3414 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3416 /* Clear rest using the GC of the original non-cursor face. */
3417 if (width < background_width)
3419 int y = s->y;
3420 int w = background_width - width, h = s->height;
3421 XRectangle r;
3422 GC gc;
3424 if (!s->row->reversed_p)
3425 x += width;
3426 else
3427 x = s->x;
3428 if (s->row->mouse_face_p
3429 && cursor_in_mouse_face_p (s->w))
3431 x_set_mouse_face_gc (s);
3432 gc = s->gc;
3434 else
3435 gc = s->face->gc;
3437 get_glyph_string_clip_rect (s, &r);
3438 x_set_clip_rectangles (s->f, gc, &r, 1);
3440 if (s->face->stipple)
3442 /* Fill background with a stipple pattern. */
3443 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3444 x_fill_rectangle (s->f, gc, x, y, w, h);
3445 XSetFillStyle (s->display, gc, FillSolid);
3447 else
3449 XGCValues xgcv;
3450 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3451 XSetForeground (s->display, gc, xgcv.background);
3452 x_fill_rectangle (s->f, gc, x, y, w, h);
3453 XSetForeground (s->display, gc, xgcv.foreground);
3456 x_reset_clip_rectangles (s->f, gc);
3459 else if (!s->background_filled_p)
3461 int background_width = s->background_width;
3462 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3464 /* Don't draw into left margin, fringe or scrollbar area
3465 except for header line and mode line. */
3466 if (x < left_x && !s->row->mode_line_p)
3468 background_width -= left_x - x;
3469 x = left_x;
3471 if (background_width > 0)
3472 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3475 s->background_filled_p = true;
3479 Draw a wavy line under S. The wave fills wave_height pixels from y0.
3481 x0 wave_length = 2
3483 y0 * * * * *
3484 |* * * * * * * * *
3485 wave_height = 3 | * * * *
3489 static void
3490 x_draw_underwave (struct glyph_string *s)
3492 int wave_height = 3, wave_length = 2;
3493 #ifdef USE_CAIRO
3494 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
3495 s->width, wave_height, wave_length);
3496 #else /* not USE_CAIRO */
3497 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
3498 bool odd;
3499 XRectangle wave_clip, string_clip, final_clip;
3501 dx = wave_length;
3502 dy = wave_height - 1;
3503 x0 = s->x;
3504 y0 = s->ybase - wave_height + 3;
3505 width = s->width;
3506 xmax = x0 + width;
3508 /* Find and set clipping rectangle */
3510 wave_clip.x = x0;
3511 wave_clip.y = y0;
3512 wave_clip.width = width;
3513 wave_clip.height = wave_height;
3514 get_glyph_string_clip_rect (s, &string_clip);
3516 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
3517 return;
3519 XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
3521 /* Draw the waves */
3523 x1 = x0 - (x0 % dx);
3524 x2 = x1 + dx;
3525 odd = (x1 / dx) & 1;
3526 y1 = y2 = y0;
3528 if (odd)
3529 y1 += dy;
3530 else
3531 y2 += dy;
3533 if (INT_MAX - dx < xmax)
3534 emacs_abort ();
3536 while (x1 <= xmax)
3538 XDrawLine (s->display, FRAME_X_DRAWABLE (s->f), s->gc, x1, y1, x2, y2);
3539 x1 = x2, y1 = y2;
3540 x2 += dx, y2 = y0 + odd*dy;
3541 odd = !odd;
3544 /* Restore previous clipping rectangle(s) */
3545 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
3546 #endif /* not USE_CAIRO */
3550 /* Draw glyph string S. */
3552 static void
3553 x_draw_glyph_string (struct glyph_string *s)
3555 bool relief_drawn_p = false;
3557 /* If S draws into the background of its successors, draw the
3558 background of the successors first so that S can draw into it.
3559 This makes S->next use XDrawString instead of XDrawImageString. */
3560 if (s->next && s->right_overhang && !s->for_overlaps)
3562 int width;
3563 struct glyph_string *next;
3565 for (width = 0, next = s->next;
3566 next && width < s->right_overhang;
3567 width += next->width, next = next->next)
3568 if (next->first_glyph->type != IMAGE_GLYPH)
3570 x_set_glyph_string_gc (next);
3571 x_set_glyph_string_clipping (next);
3572 if (next->first_glyph->type == STRETCH_GLYPH)
3573 x_draw_stretch_glyph_string (next);
3574 else
3575 x_draw_glyph_string_background (next, true);
3576 next->num_clips = 0;
3580 /* Set up S->gc, set clipping and draw S. */
3581 x_set_glyph_string_gc (s);
3583 /* Draw relief (if any) in advance for char/composition so that the
3584 glyph string can be drawn over it. */
3585 if (!s->for_overlaps
3586 && s->face->box != FACE_NO_BOX
3587 && (s->first_glyph->type == CHAR_GLYPH
3588 || s->first_glyph->type == COMPOSITE_GLYPH))
3591 x_set_glyph_string_clipping (s);
3592 x_draw_glyph_string_background (s, true);
3593 x_draw_glyph_string_box (s);
3594 x_set_glyph_string_clipping (s);
3595 relief_drawn_p = true;
3597 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
3598 && !s->clip_tail
3599 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
3600 || (s->next && s->next->hl != s->hl && s->right_overhang)))
3601 /* We must clip just this glyph. left_overhang part has already
3602 drawn when s->prev was drawn, and right_overhang part will be
3603 drawn later when s->next is drawn. */
3604 x_set_glyph_string_clipping_exactly (s, s);
3605 else
3606 x_set_glyph_string_clipping (s);
3608 switch (s->first_glyph->type)
3610 case IMAGE_GLYPH:
3611 x_draw_image_glyph_string (s);
3612 break;
3614 case XWIDGET_GLYPH:
3615 x_draw_xwidget_glyph_string (s);
3616 break;
3618 case STRETCH_GLYPH:
3619 x_draw_stretch_glyph_string (s);
3620 break;
3622 case CHAR_GLYPH:
3623 if (s->for_overlaps)
3624 s->background_filled_p = true;
3625 else
3626 x_draw_glyph_string_background (s, false);
3627 x_draw_glyph_string_foreground (s);
3628 break;
3630 case COMPOSITE_GLYPH:
3631 if (s->for_overlaps || (s->cmp_from > 0
3632 && ! s->first_glyph->u.cmp.automatic))
3633 s->background_filled_p = true;
3634 else
3635 x_draw_glyph_string_background (s, true);
3636 x_draw_composite_glyph_string_foreground (s);
3637 break;
3639 case GLYPHLESS_GLYPH:
3640 if (s->for_overlaps)
3641 s->background_filled_p = true;
3642 else
3643 x_draw_glyph_string_background (s, true);
3644 x_draw_glyphless_glyph_string_foreground (s);
3645 break;
3647 default:
3648 emacs_abort ();
3651 if (!s->for_overlaps)
3653 /* Draw underline. */
3654 if (s->face->underline_p)
3656 if (s->face->underline_type == FACE_UNDER_WAVE)
3658 if (s->face->underline_defaulted_p)
3659 x_draw_underwave (s);
3660 else
3662 XGCValues xgcv;
3663 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3664 XSetForeground (s->display, s->gc, s->face->underline_color);
3665 x_draw_underwave (s);
3666 XSetForeground (s->display, s->gc, xgcv.foreground);
3669 else if (s->face->underline_type == FACE_UNDER_LINE)
3671 unsigned long thickness, position;
3672 int y;
3674 if (s->prev && s->prev->face->underline_p
3675 && s->prev->face->underline_type == FACE_UNDER_LINE)
3677 /* We use the same underline style as the previous one. */
3678 thickness = s->prev->underline_thickness;
3679 position = s->prev->underline_position;
3681 else
3683 struct font *font = font_for_underline_metrics (s);
3685 /* Get the underline thickness. Default is 1 pixel. */
3686 if (font && font->underline_thickness > 0)
3687 thickness = font->underline_thickness;
3688 else
3689 thickness = 1;
3690 if (x_underline_at_descent_line)
3691 position = (s->height - thickness) - (s->ybase - s->y);
3692 else
3694 /* Get the underline position. This is the recommended
3695 vertical offset in pixels from the baseline to the top of
3696 the underline. This is a signed value according to the
3697 specs, and its default is
3699 ROUND ((maximum descent) / 2), with
3700 ROUND(x) = floor (x + 0.5) */
3702 if (x_use_underline_position_properties
3703 && font && font->underline_position >= 0)
3704 position = font->underline_position;
3705 else if (font)
3706 position = (font->descent + 1) / 2;
3707 else
3708 position = underline_minimum_offset;
3710 position = max (position, underline_minimum_offset);
3712 /* Check the sanity of thickness and position. We should
3713 avoid drawing underline out of the current line area. */
3714 if (s->y + s->height <= s->ybase + position)
3715 position = (s->height - 1) - (s->ybase - s->y);
3716 if (s->y + s->height < s->ybase + position + thickness)
3717 thickness = (s->y + s->height) - (s->ybase + position);
3718 s->underline_thickness = thickness;
3719 s->underline_position = position;
3720 y = s->ybase + position;
3721 if (s->face->underline_defaulted_p)
3722 x_fill_rectangle (s->f, s->gc,
3723 s->x, y, s->width, thickness);
3724 else
3726 XGCValues xgcv;
3727 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3728 XSetForeground (s->display, s->gc, s->face->underline_color);
3729 x_fill_rectangle (s->f, s->gc,
3730 s->x, y, s->width, thickness);
3731 XSetForeground (s->display, s->gc, xgcv.foreground);
3735 /* Draw overline. */
3736 if (s->face->overline_p)
3738 unsigned long dy = 0, h = 1;
3740 if (s->face->overline_color_defaulted_p)
3741 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3742 s->width, h);
3743 else
3745 XGCValues xgcv;
3746 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3747 XSetForeground (s->display, s->gc, s->face->overline_color);
3748 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3749 s->width, h);
3750 XSetForeground (s->display, s->gc, xgcv.foreground);
3754 /* Draw strike-through. */
3755 if (s->face->strike_through_p)
3757 /* Y-coordinate and height of the glyph string's first
3758 glyph. We cannot use s->y and s->height because those
3759 could be larger if there are taller display elements
3760 (e.g., characters displayed with a larger font) in the
3761 same glyph row. */
3762 int glyph_y = s->ybase - s->first_glyph->ascent;
3763 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
3764 /* Strike-through width and offset from the glyph string's
3765 top edge. */
3766 unsigned long h = 1;
3767 unsigned long dy = (glyph_height - h) / 2;
3769 if (s->face->strike_through_color_defaulted_p)
3770 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
3771 s->width, h);
3772 else
3774 XGCValues xgcv;
3775 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3776 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3777 x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
3778 s->width, h);
3779 XSetForeground (s->display, s->gc, xgcv.foreground);
3783 /* Draw relief if not yet drawn. */
3784 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3785 x_draw_glyph_string_box (s);
3787 if (s->prev)
3789 struct glyph_string *prev;
3791 for (prev = s->prev; prev; prev = prev->prev)
3792 if (prev->hl != s->hl
3793 && prev->x + prev->width + prev->right_overhang > s->x)
3795 /* As prev was drawn while clipped to its own area, we
3796 must draw the right_overhang part using s->hl now. */
3797 enum draw_glyphs_face save = prev->hl;
3799 prev->hl = s->hl;
3800 x_set_glyph_string_gc (prev);
3801 x_set_glyph_string_clipping_exactly (s, prev);
3802 if (prev->first_glyph->type == CHAR_GLYPH)
3803 x_draw_glyph_string_foreground (prev);
3804 else
3805 x_draw_composite_glyph_string_foreground (prev);
3806 x_reset_clip_rectangles (prev->f, prev->gc);
3807 prev->hl = save;
3808 prev->num_clips = 0;
3812 if (s->next)
3814 struct glyph_string *next;
3816 for (next = s->next; next; next = next->next)
3817 if (next->hl != s->hl
3818 && next->x - next->left_overhang < s->x + s->width)
3820 /* As next will be drawn while clipped to its own area,
3821 we must draw the left_overhang part using s->hl now. */
3822 enum draw_glyphs_face save = next->hl;
3824 next->hl = s->hl;
3825 x_set_glyph_string_gc (next);
3826 x_set_glyph_string_clipping_exactly (s, next);
3827 if (next->first_glyph->type == CHAR_GLYPH)
3828 x_draw_glyph_string_foreground (next);
3829 else
3830 x_draw_composite_glyph_string_foreground (next);
3831 x_reset_clip_rectangles (next->f, next->gc);
3832 next->hl = save;
3833 next->num_clips = 0;
3834 next->clip_head = s->next;
3839 /* Reset clipping. */
3840 x_reset_clip_rectangles (s->f, s->gc);
3841 s->num_clips = 0;
3844 /* Shift display to make room for inserted glyphs. */
3846 static void
3847 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
3849 /* Never called on a GUI frame, see
3850 http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
3852 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
3853 f->output_data.x->normal_gc,
3854 x, y, width, height,
3855 x + shift_by, y);
3858 /* Delete N glyphs at the nominal cursor position. Not implemented
3859 for X frames. */
3861 static void
3862 x_delete_glyphs (struct frame *f, register int n)
3864 emacs_abort ();
3868 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
3869 If they are <= 0, this is probably an error. */
3871 static ATTRIBUTE_UNUSED void
3872 x_clear_area1 (Display *dpy, Window window,
3873 int x, int y, int width, int height, int exposures)
3875 eassert (width > 0 && height > 0);
3876 XClearArea (dpy, window, x, y, width, height, exposures);
3879 void
3880 x_clear_area (struct frame *f, int x, int y, int width, int height)
3882 #ifdef USE_CAIRO
3883 cairo_t *cr;
3885 eassert (width > 0 && height > 0);
3887 cr = x_begin_cr_clip (f, NULL);
3888 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
3889 cairo_rectangle (cr, x, y, width, height);
3890 cairo_fill (cr);
3891 x_end_cr_clip (f);
3892 #else
3893 if (FRAME_X_DOUBLE_BUFFERED_P (f))
3894 XFillRectangle (FRAME_X_DISPLAY (f),
3895 FRAME_X_DRAWABLE (f),
3896 f->output_data.x->reverse_gc,
3897 x, y, width, height);
3898 else
3899 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3900 x, y, width, height, False);
3901 #endif
3905 /* Clear an entire frame. */
3907 static void
3908 x_clear_frame (struct frame *f)
3910 /* Clearing the frame will erase any cursor, so mark them all as no
3911 longer visible. */
3912 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3914 block_input ();
3916 font_drop_xrender_surfaces (f);
3917 x_clear_window (f);
3919 /* We have to clear the scroll bars. If we have changed colors or
3920 something like that, then they should be notified. */
3921 x_scroll_bar_clear (f);
3923 XFlush (FRAME_X_DISPLAY (f));
3925 unblock_input ();
3928 /* RIF: Show hourglass cursor on frame F. */
3930 static void
3931 x_show_hourglass (struct frame *f)
3933 Display *dpy = FRAME_X_DISPLAY (f);
3935 if (dpy)
3937 struct x_output *x = FRAME_X_OUTPUT (f);
3938 #ifdef USE_X_TOOLKIT
3939 if (x->widget)
3940 #else
3941 if (FRAME_OUTER_WINDOW (f))
3942 #endif
3944 x->hourglass_p = true;
3946 if (!x->hourglass_window)
3948 unsigned long mask = CWCursor;
3949 XSetWindowAttributes attrs;
3950 #ifdef USE_GTK
3951 Window parent = FRAME_X_WINDOW (f);
3952 #else
3953 Window parent = FRAME_OUTER_WINDOW (f);
3954 #endif
3955 attrs.cursor = x->hourglass_cursor;
3957 x->hourglass_window = XCreateWindow
3958 (dpy, parent, 0, 0, 32000, 32000, 0, 0,
3959 InputOnly, CopyFromParent, mask, &attrs);
3962 XMapRaised (dpy, x->hourglass_window);
3963 XFlush (dpy);
3968 /* RIF: Cancel hourglass cursor on frame F. */
3970 static void
3971 x_hide_hourglass (struct frame *f)
3973 struct x_output *x = FRAME_X_OUTPUT (f);
3975 /* Watch out for newly created frames. */
3976 if (x->hourglass_window)
3978 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
3979 /* Sync here because XTread_socket looks at the
3980 hourglass_p flag that is reset to zero below. */
3981 XSync (FRAME_X_DISPLAY (f), False);
3982 x->hourglass_p = false;
3986 /* Invert the middle quarter of the frame for .15 sec. */
3988 static void
3989 XTflash (struct frame *f)
3991 block_input ();
3994 #ifdef USE_GTK
3995 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3996 when the scroll bars and the edit widget share the same X window. */
3997 GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
3998 #ifdef HAVE_GTK3
3999 cairo_t *cr = gdk_cairo_create (window);
4000 cairo_set_source_rgb (cr, 1, 1, 1);
4001 cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
4002 #define XFillRectangle(d, win, gc, x, y, w, h) \
4003 do { \
4004 cairo_rectangle (cr, x, y, w, h); \
4005 cairo_fill (cr); \
4007 while (false)
4008 #else /* ! HAVE_GTK3 */
4009 GdkGCValues vals;
4010 GdkGC *gc;
4011 vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
4012 ^ FRAME_BACKGROUND_PIXEL (f));
4013 vals.function = GDK_XOR;
4014 gc = gdk_gc_new_with_values (window,
4015 &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
4016 #define XFillRectangle(d, win, gc, x, y, w, h) \
4017 gdk_draw_rectangle (window, gc, true, x, y, w, h)
4018 #endif /* ! HAVE_GTK3 */
4019 #else /* ! USE_GTK */
4020 GC gc;
4022 /* Create a GC that will use the GXxor function to flip foreground
4023 pixels into background pixels. */
4025 XGCValues values;
4027 values.function = GXxor;
4028 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
4029 ^ FRAME_BACKGROUND_PIXEL (f));
4031 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4032 GCFunction | GCForeground, &values);
4034 #endif
4036 /* Get the height not including a menu bar widget. */
4037 int height = FRAME_PIXEL_HEIGHT (f);
4038 /* Height of each line to flash. */
4039 int flash_height = FRAME_LINE_HEIGHT (f);
4040 /* These will be the left and right margins of the rectangles. */
4041 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4042 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4043 int width = flash_right - flash_left;
4045 /* If window is tall, flash top and bottom line. */
4046 if (height > 3 * FRAME_LINE_HEIGHT (f))
4048 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4049 flash_left,
4050 (FRAME_INTERNAL_BORDER_WIDTH (f)
4051 + FRAME_TOP_MARGIN_HEIGHT (f)),
4052 width, flash_height);
4053 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4054 flash_left,
4055 (height - flash_height
4056 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4057 width, flash_height);
4060 else
4061 /* If it is short, flash it all. */
4062 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4063 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4064 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4066 x_flush (f);
4069 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
4070 struct timespec wakeup = timespec_add (current_timespec (), delay);
4072 /* Keep waiting until past the time wakeup or any input gets
4073 available. */
4074 while (! detect_input_pending ())
4076 struct timespec current = current_timespec ();
4077 struct timespec timeout;
4079 /* Break if result would not be positive. */
4080 if (timespec_cmp (wakeup, current) <= 0)
4081 break;
4083 /* How long `select' should wait. */
4084 timeout = make_timespec (0, 10 * 1000 * 1000);
4086 /* Try to wait that long--but we might wake up sooner. */
4087 pselect (0, NULL, NULL, NULL, &timeout, NULL);
4091 /* If window is tall, flash top and bottom line. */
4092 if (height > 3 * FRAME_LINE_HEIGHT (f))
4094 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4095 flash_left,
4096 (FRAME_INTERNAL_BORDER_WIDTH (f)
4097 + FRAME_TOP_MARGIN_HEIGHT (f)),
4098 width, flash_height);
4099 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4100 flash_left,
4101 (height - flash_height
4102 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4103 width, flash_height);
4105 else
4106 /* If it is short, flash it all. */
4107 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4108 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4109 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4111 #ifdef USE_GTK
4112 #ifdef HAVE_GTK3
4113 cairo_destroy (cr);
4114 #else
4115 g_object_unref (G_OBJECT (gc));
4116 #endif
4117 #undef XFillRectangle
4118 #else
4119 XFreeGC (FRAME_X_DISPLAY (f), gc);
4120 #endif
4121 x_flush (f);
4125 unblock_input ();
4129 static void
4130 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
4132 block_input ();
4133 FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
4134 unblock_input ();
4138 /* Make audible bell. */
4140 static void
4141 XTring_bell (struct frame *f)
4143 if (FRAME_X_DISPLAY (f))
4145 if (visible_bell)
4146 XTflash (f);
4147 else
4149 block_input ();
4150 #ifdef HAVE_XKB
4151 XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
4152 #else
4153 XBell (FRAME_X_DISPLAY (f), 0);
4154 #endif
4155 XFlush (FRAME_X_DISPLAY (f));
4156 unblock_input ();
4161 /***********************************************************************
4162 Line Dance
4163 ***********************************************************************/
4165 /* Perform an insert-lines or delete-lines operation, inserting N
4166 lines or deleting -N lines at vertical position VPOS. */
4168 static void
4169 x_ins_del_lines (struct frame *f, int vpos, int n)
4171 emacs_abort ();
4175 /* Scroll part of the display as described by RUN. */
4177 static void
4178 x_scroll_run (struct window *w, struct run *run)
4180 struct frame *f = XFRAME (w->frame);
4181 int x, y, width, height, from_y, to_y, bottom_y;
4183 /* Get frame-relative bounding box of the text display area of W,
4184 without mode lines. Include in this box the left and right
4185 fringe of W. */
4186 window_box (w, ANY_AREA, &x, &y, &width, &height);
4188 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4189 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4190 bottom_y = y + height;
4192 if (to_y < from_y)
4194 /* Scrolling up. Make sure we don't copy part of the mode
4195 line at the bottom. */
4196 if (from_y + run->height > bottom_y)
4197 height = bottom_y - from_y;
4198 else
4199 height = run->height;
4201 else
4203 /* Scrolling down. Make sure we don't copy over the mode line.
4204 at the bottom. */
4205 if (to_y + run->height > bottom_y)
4206 height = bottom_y - to_y;
4207 else
4208 height = run->height;
4211 block_input ();
4213 /* Cursor off. Will be switched on again in x_update_window_end. */
4214 x_clear_cursor (w);
4216 #ifdef USE_CAIRO
4217 SET_FRAME_GARBAGED (f);
4218 #else
4219 XCopyArea (FRAME_X_DISPLAY (f),
4220 FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
4221 f->output_data.x->normal_gc,
4222 x, from_y,
4223 width, height,
4224 x, to_y);
4225 #endif
4227 unblock_input ();
4232 /***********************************************************************
4233 Exposure Events
4234 ***********************************************************************/
4237 static void
4238 frame_highlight (struct frame *f)
4240 /* We used to only do this if Vx_no_window_manager was non-nil, but
4241 the ICCCM (section 4.1.6) says that the window's border pixmap
4242 and border pixel are window attributes which are "private to the
4243 client", so we can always change it to whatever we want. */
4244 block_input ();
4245 /* I recently started to get errors in this XSetWindowBorder, depending on
4246 the window-manager in use, tho something more is at play since I've been
4247 using that same window-manager binary for ever. Let's not crash just
4248 because of this (bug#9310). */
4249 x_catch_errors (FRAME_X_DISPLAY (f));
4250 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4251 f->output_data.x->border_pixel);
4252 x_uncatch_errors ();
4253 unblock_input ();
4254 x_update_cursor (f, true);
4255 x_set_frame_alpha (f);
4258 static void
4259 frame_unhighlight (struct frame *f)
4261 /* We used to only do this if Vx_no_window_manager was non-nil, but
4262 the ICCCM (section 4.1.6) says that the window's border pixmap
4263 and border pixel are window attributes which are "private to the
4264 client", so we can always change it to whatever we want. */
4265 block_input ();
4266 /* Same as above for XSetWindowBorder (bug#9310). */
4267 x_catch_errors (FRAME_X_DISPLAY (f));
4268 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4269 f->output_data.x->border_tile);
4270 x_uncatch_errors ();
4271 unblock_input ();
4272 x_update_cursor (f, true);
4273 x_set_frame_alpha (f);
4276 /* The focus has changed. Update the frames as necessary to reflect
4277 the new situation. Note that we can't change the selected frame
4278 here, because the Lisp code we are interrupting might become confused.
4279 Each event gets marked with the frame in which it occurred, so the
4280 Lisp code can tell when the switch took place by examining the events. */
4282 static void
4283 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
4285 struct frame *old_focus = dpyinfo->x_focus_frame;
4287 if (frame != dpyinfo->x_focus_frame)
4289 /* Set this before calling other routines, so that they see
4290 the correct value of x_focus_frame. */
4291 dpyinfo->x_focus_frame = frame;
4293 if (old_focus && old_focus->auto_lower)
4294 x_lower_frame (old_focus);
4296 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4297 dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
4298 else
4299 dpyinfo->x_pending_autoraise_frame = NULL;
4302 x_frame_rehighlight (dpyinfo);
4305 /* Handle FocusIn and FocusOut state changes for FRAME.
4306 If FRAME has focus and there exists more than one frame, puts
4307 a FOCUS_IN_EVENT into *BUFP. */
4309 static void
4310 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
4312 if (type == FocusIn)
4314 if (dpyinfo->x_focus_event_frame != frame)
4316 x_new_focus_frame (dpyinfo, frame);
4317 dpyinfo->x_focus_event_frame = frame;
4319 /* Don't stop displaying the initial startup message
4320 for a switch-frame event we don't need. */
4321 /* When run as a daemon, Vterminal_frame is always NIL. */
4322 bufp->arg = (((NILP (Vterminal_frame)
4323 || ! FRAME_X_P (XFRAME (Vterminal_frame))
4324 || EQ (Fdaemonp (), Qt))
4325 && CONSP (Vframe_list)
4326 && !NILP (XCDR (Vframe_list)))
4327 ? Qt : Qnil);
4328 bufp->kind = FOCUS_IN_EVENT;
4329 XSETFRAME (bufp->frame_or_window, frame);
4332 frame->output_data.x->focus_state |= state;
4334 #ifdef HAVE_X_I18N
4335 if (FRAME_XIC (frame))
4336 XSetICFocus (FRAME_XIC (frame));
4337 #endif
4339 else if (type == FocusOut)
4341 frame->output_data.x->focus_state &= ~state;
4343 if (dpyinfo->x_focus_event_frame == frame)
4345 dpyinfo->x_focus_event_frame = 0;
4346 x_new_focus_frame (dpyinfo, 0);
4348 bufp->kind = FOCUS_OUT_EVENT;
4349 XSETFRAME (bufp->frame_or_window, frame);
4352 #ifdef HAVE_X_I18N
4353 if (FRAME_XIC (frame))
4354 XUnsetICFocus (FRAME_XIC (frame));
4355 #endif
4356 if (frame->pointer_invisible)
4357 XTtoggle_invisible_pointer (frame, false);
4361 /* Return the Emacs frame-object corresponding to an X window.
4362 It could be the frame's main window or an icon window. */
4364 static struct frame *
4365 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4367 Lisp_Object tail, frame;
4368 struct frame *f;
4370 if (wdesc == None)
4371 return NULL;
4373 FOR_EACH_FRAME (tail, frame)
4375 f = XFRAME (frame);
4376 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4377 continue;
4378 if (f->output_data.x->hourglass_window == wdesc)
4379 return f;
4380 #ifdef USE_X_TOOLKIT
4381 if ((f->output_data.x->edit_widget
4382 && XtWindow (f->output_data.x->edit_widget) == wdesc)
4383 /* A tooltip frame? */
4384 || (!f->output_data.x->edit_widget
4385 && FRAME_X_WINDOW (f) == wdesc)
4386 || f->output_data.x->icon_desc == wdesc)
4387 return f;
4388 #else /* not USE_X_TOOLKIT */
4389 #ifdef USE_GTK
4390 if (f->output_data.x->edit_widget)
4392 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4393 struct x_output *x = f->output_data.x;
4394 if (gwdesc != 0 && gwdesc == x->edit_widget)
4395 return f;
4397 #endif /* USE_GTK */
4398 if (FRAME_X_WINDOW (f) == wdesc
4399 || f->output_data.x->icon_desc == wdesc)
4400 return f;
4401 #endif /* not USE_X_TOOLKIT */
4403 return 0;
4406 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4408 /* Like x_window_to_frame but also compares the window with the widget's
4409 windows. */
4411 static struct frame *
4412 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4414 Lisp_Object tail, frame;
4415 struct frame *f, *found = NULL;
4416 struct x_output *x;
4418 if (wdesc == None)
4419 return NULL;
4421 FOR_EACH_FRAME (tail, frame)
4423 if (found)
4424 break;
4425 f = XFRAME (frame);
4426 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
4428 /* This frame matches if the window is any of its widgets. */
4429 x = f->output_data.x;
4430 if (x->hourglass_window == wdesc)
4431 found = f;
4432 else if (x->widget)
4434 #ifdef USE_GTK
4435 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4436 if (gwdesc != 0
4437 && gtk_widget_get_toplevel (gwdesc) == x->widget)
4438 found = f;
4439 #else
4440 if (wdesc == XtWindow (x->widget)
4441 || wdesc == XtWindow (x->column_widget)
4442 || wdesc == XtWindow (x->edit_widget))
4443 found = f;
4444 /* Match if the window is this frame's menubar. */
4445 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
4446 found = f;
4447 #endif
4449 else if (FRAME_X_WINDOW (f) == wdesc)
4450 /* A tooltip frame. */
4451 found = f;
4455 return found;
4458 /* Likewise, but consider only the menu bar widget. */
4460 static struct frame *
4461 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
4462 const XEvent *event)
4464 Window wdesc = event->xany.window;
4465 Lisp_Object tail, frame;
4466 struct frame *f;
4467 struct x_output *x;
4469 if (wdesc == None)
4470 return NULL;
4472 FOR_EACH_FRAME (tail, frame)
4474 f = XFRAME (frame);
4475 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4476 continue;
4477 x = f->output_data.x;
4478 #ifdef USE_GTK
4479 if (x->menubar_widget && xg_event_is_for_menubar (f, event))
4480 return f;
4481 #else
4482 /* Match if the window is this frame's menubar. */
4483 if (x->menubar_widget
4484 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
4485 return f;
4486 #endif
4488 return 0;
4491 /* Return the frame whose principal (outermost) window is WDESC.
4492 If WDESC is some other (smaller) window, we return 0. */
4494 struct frame *
4495 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
4497 Lisp_Object tail, frame;
4498 struct frame *f;
4499 struct x_output *x;
4501 if (wdesc == None)
4502 return NULL;
4504 FOR_EACH_FRAME (tail, frame)
4506 f = XFRAME (frame);
4507 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
4508 continue;
4509 x = f->output_data.x;
4511 if (x->widget)
4513 /* This frame matches if the window is its topmost widget. */
4514 #ifdef USE_GTK
4515 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
4516 if (gwdesc == x->widget)
4517 return f;
4518 #else
4519 if (wdesc == XtWindow (x->widget))
4520 return f;
4521 #endif
4523 else if (FRAME_X_WINDOW (f) == wdesc)
4524 /* Tooltip frame. */
4525 return f;
4527 return 0;
4530 #else /* !USE_X_TOOLKIT && !USE_GTK */
4532 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
4533 #define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
4535 #endif /* USE_X_TOOLKIT || USE_GTK */
4537 /* The focus may have changed. Figure out if it is a real focus change,
4538 by checking both FocusIn/Out and Enter/LeaveNotify events.
4540 Returns FOCUS_IN_EVENT event in *BUFP. */
4542 static void
4543 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
4544 const XEvent *event, struct input_event *bufp)
4546 if (!frame)
4547 return;
4549 switch (event->type)
4551 case EnterNotify:
4552 case LeaveNotify:
4554 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
4555 int focus_state
4556 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
4558 if (event->xcrossing.detail != NotifyInferior
4559 && event->xcrossing.focus
4560 && ! (focus_state & FOCUS_EXPLICIT))
4561 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
4562 FOCUS_IMPLICIT,
4563 dpyinfo, frame, bufp);
4565 break;
4567 case FocusIn:
4568 case FocusOut:
4569 x_focus_changed (event->type,
4570 (event->xfocus.detail == NotifyPointer ?
4571 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
4572 dpyinfo, frame, bufp);
4573 break;
4575 case ClientMessage:
4576 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
4578 enum xembed_message msg = event->xclient.data.l[1];
4579 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
4580 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
4582 break;
4587 #if !defined USE_X_TOOLKIT && !defined USE_GTK
4588 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4590 void
4591 x_mouse_leave (struct x_display_info *dpyinfo)
4593 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4595 #endif
4597 /* The focus has changed, or we have redirected a frame's focus to
4598 another frame (this happens when a frame uses a surrogate
4599 mini-buffer frame). Shift the highlight as appropriate.
4601 The FRAME argument doesn't necessarily have anything to do with which
4602 frame is being highlighted or un-highlighted; we only use it to find
4603 the appropriate X display info. */
4605 static void
4606 XTframe_rehighlight (struct frame *frame)
4608 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
4611 static void
4612 x_frame_rehighlight (struct x_display_info *dpyinfo)
4614 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4616 if (dpyinfo->x_focus_frame)
4618 dpyinfo->x_highlight_frame
4619 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4620 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4621 : dpyinfo->x_focus_frame);
4622 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4624 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
4625 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4628 else
4629 dpyinfo->x_highlight_frame = 0;
4631 if (dpyinfo->x_highlight_frame != old_highlight)
4633 if (old_highlight)
4634 frame_unhighlight (old_highlight);
4635 if (dpyinfo->x_highlight_frame)
4636 frame_highlight (dpyinfo->x_highlight_frame);
4642 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
4644 /* Initialize mode_switch_bit and modifier_meaning. */
4645 static void
4646 x_find_modifier_meanings (struct x_display_info *dpyinfo)
4648 int min_code, max_code;
4649 KeySym *syms;
4650 int syms_per_code;
4651 XModifierKeymap *mods;
4653 dpyinfo->meta_mod_mask = 0;
4654 dpyinfo->shift_lock_mask = 0;
4655 dpyinfo->alt_mod_mask = 0;
4656 dpyinfo->super_mod_mask = 0;
4657 dpyinfo->hyper_mod_mask = 0;
4659 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
4661 syms = XGetKeyboardMapping (dpyinfo->display,
4662 min_code, max_code - min_code + 1,
4663 &syms_per_code);
4664 mods = XGetModifierMapping (dpyinfo->display);
4666 /* Scan the modifier table to see which modifier bits the Meta and
4667 Alt keysyms are on. */
4669 int row, col; /* The row and column in the modifier table. */
4670 bool found_alt_or_meta;
4672 for (row = 3; row < 8; row++)
4674 found_alt_or_meta = false;
4675 for (col = 0; col < mods->max_keypermod; col++)
4677 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
4679 /* Zeroes are used for filler. Skip them. */
4680 if (code == 0)
4681 continue;
4683 /* Are any of this keycode's keysyms a meta key? */
4685 int code_col;
4687 for (code_col = 0; code_col < syms_per_code; code_col++)
4689 int sym = syms[((code - min_code) * syms_per_code) + code_col];
4691 switch (sym)
4693 case XK_Meta_L:
4694 case XK_Meta_R:
4695 found_alt_or_meta = true;
4696 dpyinfo->meta_mod_mask |= (1 << row);
4697 break;
4699 case XK_Alt_L:
4700 case XK_Alt_R:
4701 found_alt_or_meta = true;
4702 dpyinfo->alt_mod_mask |= (1 << row);
4703 break;
4705 case XK_Hyper_L:
4706 case XK_Hyper_R:
4707 if (!found_alt_or_meta)
4708 dpyinfo->hyper_mod_mask |= (1 << row);
4709 code_col = syms_per_code;
4710 col = mods->max_keypermod;
4711 break;
4713 case XK_Super_L:
4714 case XK_Super_R:
4715 if (!found_alt_or_meta)
4716 dpyinfo->super_mod_mask |= (1 << row);
4717 code_col = syms_per_code;
4718 col = mods->max_keypermod;
4719 break;
4721 case XK_Shift_Lock:
4722 /* Ignore this if it's not on the lock modifier. */
4723 if (!found_alt_or_meta && ((1 << row) == LockMask))
4724 dpyinfo->shift_lock_mask = LockMask;
4725 code_col = syms_per_code;
4726 col = mods->max_keypermod;
4727 break;
4735 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4736 if (! dpyinfo->meta_mod_mask)
4738 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
4739 dpyinfo->alt_mod_mask = 0;
4742 /* If some keys are both alt and meta,
4743 make them just meta, not alt. */
4744 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
4746 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
4749 XFree (syms);
4750 XFreeModifiermap (mods);
4753 /* Convert between the modifier bits X uses and the modifier bits
4754 Emacs uses. */
4757 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
4759 int mod_ctrl = ctrl_modifier;
4760 int mod_meta = meta_modifier;
4761 int mod_alt = alt_modifier;
4762 int mod_hyper = hyper_modifier;
4763 int mod_super = super_modifier;
4764 Lisp_Object tem;
4766 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
4767 if (INTEGERP (tem)) mod_ctrl = XINT (tem) & INT_MAX;
4768 tem = Fget (Vx_alt_keysym, Qmodifier_value);
4769 if (INTEGERP (tem)) mod_alt = XINT (tem) & INT_MAX;
4770 tem = Fget (Vx_meta_keysym, Qmodifier_value);
4771 if (INTEGERP (tem)) mod_meta = XINT (tem) & INT_MAX;
4772 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
4773 if (INTEGERP (tem)) mod_hyper = XINT (tem) & INT_MAX;
4774 tem = Fget (Vx_super_keysym, Qmodifier_value);
4775 if (INTEGERP (tem)) mod_super = XINT (tem) & INT_MAX;
4777 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
4778 | ((state & ControlMask) ? mod_ctrl : 0)
4779 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
4780 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
4781 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
4782 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
4785 static int
4786 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, EMACS_INT state)
4788 EMACS_INT mod_ctrl = ctrl_modifier;
4789 EMACS_INT mod_meta = meta_modifier;
4790 EMACS_INT mod_alt = alt_modifier;
4791 EMACS_INT mod_hyper = hyper_modifier;
4792 EMACS_INT mod_super = super_modifier;
4794 Lisp_Object tem;
4796 tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
4797 if (INTEGERP (tem)) mod_ctrl = XINT (tem);
4798 tem = Fget (Vx_alt_keysym, Qmodifier_value);
4799 if (INTEGERP (tem)) mod_alt = XINT (tem);
4800 tem = Fget (Vx_meta_keysym, Qmodifier_value);
4801 if (INTEGERP (tem)) mod_meta = XINT (tem);
4802 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
4803 if (INTEGERP (tem)) mod_hyper = XINT (tem);
4804 tem = Fget (Vx_super_keysym, Qmodifier_value);
4805 if (INTEGERP (tem)) mod_super = XINT (tem);
4808 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
4809 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
4810 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
4811 | ((state & shift_modifier) ? ShiftMask : 0)
4812 | ((state & mod_ctrl) ? ControlMask : 0)
4813 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
4816 /* Convert a keysym to its name. */
4818 char *
4819 x_get_keysym_name (int keysym)
4821 char *value;
4823 block_input ();
4824 value = XKeysymToString (keysym);
4825 unblock_input ();
4827 return value;
4830 /* Mouse clicks and mouse movement. Rah.
4832 Formerly, we used PointerMotionHintMask (in standard_event_mask)
4833 so that we would have to call XQueryPointer after each MotionNotify
4834 event to ask for another such event. However, this made mouse tracking
4835 slow, and there was a bug that made it eventually stop.
4837 Simply asking for MotionNotify all the time seems to work better.
4839 In order to avoid asking for motion events and then throwing most
4840 of them away or busy-polling the server for mouse positions, we ask
4841 the server for pointer motion hints. This means that we get only
4842 one event per group of mouse movements. "Groups" are delimited by
4843 other kinds of events (focus changes and button clicks, for
4844 example), or by XQueryPointer calls; when one of these happens, we
4845 get another MotionNotify event the next time the mouse moves. This
4846 is at least as efficient as getting motion events when mouse
4847 tracking is on, and I suspect only negligibly worse when tracking
4848 is off. */
4850 /* Prepare a mouse-event in *RESULT for placement in the input queue.
4852 If the event is a button press, then note that we have grabbed
4853 the mouse. */
4855 static Lisp_Object
4856 construct_mouse_click (struct input_event *result,
4857 const XButtonEvent *event,
4858 struct frame *f)
4860 /* Make the event type NO_EVENT; we'll change that when we decide
4861 otherwise. */
4862 result->kind = MOUSE_CLICK_EVENT;
4863 result->code = event->button - Button1;
4864 result->timestamp = event->time;
4865 result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
4866 event->state)
4867 | (event->type == ButtonRelease
4868 ? up_modifier
4869 : down_modifier));
4871 XSETINT (result->x, event->x);
4872 XSETINT (result->y, event->y);
4873 XSETFRAME (result->frame_or_window, f);
4874 result->arg = Qnil;
4875 return Qnil;
4878 /* Function to report a mouse movement to the mainstream Emacs code.
4879 The input handler calls this.
4881 We have received a mouse movement event, which is given in *event.
4882 If the mouse is over a different glyph than it was last time, tell
4883 the mainstream emacs code by setting mouse_moved. If not, ask for
4884 another motion event, so we can check again the next time it moves. */
4886 static bool
4887 note_mouse_movement (struct frame *frame, const XMotionEvent *event)
4889 XRectangle *r;
4890 struct x_display_info *dpyinfo;
4892 if (!FRAME_X_OUTPUT (frame))
4893 return false;
4895 dpyinfo = FRAME_DISPLAY_INFO (frame);
4896 dpyinfo->last_mouse_movement_time = event->time;
4897 dpyinfo->last_mouse_motion_frame = frame;
4898 dpyinfo->last_mouse_motion_x = event->x;
4899 dpyinfo->last_mouse_motion_y = event->y;
4901 if (event->window != FRAME_X_WINDOW (frame))
4903 frame->mouse_moved = true;
4904 dpyinfo->last_mouse_scroll_bar = NULL;
4905 note_mouse_highlight (frame, -1, -1);
4906 dpyinfo->last_mouse_glyph_frame = NULL;
4907 return true;
4911 /* Has the mouse moved off the glyph it was on at the last sighting? */
4912 r = &dpyinfo->last_mouse_glyph;
4913 if (frame != dpyinfo->last_mouse_glyph_frame
4914 || event->x < r->x || event->x >= r->x + r->width
4915 || event->y < r->y || event->y >= r->y + r->height)
4917 frame->mouse_moved = true;
4918 dpyinfo->last_mouse_scroll_bar = NULL;
4919 note_mouse_highlight (frame, event->x, event->y);
4920 /* Remember which glyph we're now on. */
4921 remember_mouse_glyph (frame, event->x, event->y, r);
4922 dpyinfo->last_mouse_glyph_frame = frame;
4923 return true;
4926 return false;
4929 /* Return the current position of the mouse.
4930 *FP should be a frame which indicates which display to ask about.
4932 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4933 and *PART to the frame, window, and scroll bar part that the mouse
4934 is over. Set *X and *Y to the portion and whole of the mouse's
4935 position on the scroll bar.
4937 If the mouse movement started elsewhere, set *FP to the frame the
4938 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4939 the mouse is over.
4941 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
4942 was at this position.
4944 Don't store anything if we don't have a valid set of values to report.
4946 This clears the mouse_moved flag, so we can wait for the next mouse
4947 movement. */
4949 static void
4950 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4951 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
4952 Time *timestamp)
4954 struct frame *f1;
4955 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
4957 block_input ();
4959 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
4961 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
4963 if (bar->horizontal)
4964 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
4965 else
4966 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
4968 else
4970 Window root;
4971 int root_x, root_y;
4973 Window dummy_window;
4974 int dummy;
4976 Lisp_Object frame, tail;
4978 /* Clear the mouse-moved flag for every frame on this display. */
4979 FOR_EACH_FRAME (tail, frame)
4980 if (FRAME_X_P (XFRAME (frame))
4981 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
4982 XFRAME (frame)->mouse_moved = false;
4984 dpyinfo->last_mouse_scroll_bar = NULL;
4986 /* Figure out which root window we're on. */
4987 XQueryPointer (FRAME_X_DISPLAY (*fp),
4988 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
4990 /* The root window which contains the pointer. */
4991 &root,
4993 /* Trash which we can't trust if the pointer is on
4994 a different screen. */
4995 &dummy_window,
4997 /* The position on that root window. */
4998 &root_x, &root_y,
5000 /* More trash we can't trust. */
5001 &dummy, &dummy,
5003 /* Modifier keys and pointer buttons, about which
5004 we don't care. */
5005 (unsigned int *) &dummy);
5007 /* Now we have a position on the root; find the innermost window
5008 containing the pointer. */
5010 Window win, child;
5011 #ifdef USE_GTK
5012 Window first_win = 0;
5013 #endif
5014 int win_x, win_y;
5015 int parent_x = 0, parent_y = 0;
5017 win = root;
5019 /* XTranslateCoordinates can get errors if the window
5020 structure is changing at the same time this function
5021 is running. So at least we must not crash from them. */
5023 x_catch_errors (FRAME_X_DISPLAY (*fp));
5025 if (x_mouse_grabbed (dpyinfo))
5027 /* If mouse was grabbed on a frame, give coords for that frame
5028 even if the mouse is now outside it. */
5029 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
5031 /* From-window. */
5032 root,
5034 /* To-window. */
5035 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
5037 /* From-position, to-position. */
5038 root_x, root_y, &win_x, &win_y,
5040 /* Child of win. */
5041 &child);
5042 f1 = dpyinfo->last_mouse_frame;
5044 else
5046 while (true)
5048 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
5050 /* From-window, to-window. */
5051 root, win,
5053 /* From-position, to-position. */
5054 root_x, root_y, &win_x, &win_y,
5056 /* Child of win. */
5057 &child);
5059 if (child == None || child == win)
5061 #ifdef USE_GTK
5062 /* On GTK we have not inspected WIN yet. If it has
5063 a frame and that frame has a parent, use it. */
5064 struct frame *f = x_window_to_frame (dpyinfo, win);
5066 if (f && FRAME_PARENT_FRAME (f))
5067 first_win = win;
5068 #endif
5069 break;
5071 #ifdef USE_GTK
5072 /* We don't wan't to know the innermost window. We
5073 want the edit window. For non-Gtk+ the innermost
5074 window is the edit window. For Gtk+ it might not
5075 be. It might be the tool bar for example. */
5076 if (x_window_to_frame (dpyinfo, win))
5077 /* But don't hurry. We might find a child frame
5078 beneath. */
5079 first_win = win;
5080 #endif
5081 win = child;
5082 parent_x = win_x;
5083 parent_y = win_y;
5086 #ifdef USE_GTK
5087 if (first_win)
5088 win = first_win;
5089 #endif
5091 /* Now we know that:
5092 win is the innermost window containing the pointer
5093 (XTC says it has no child containing the pointer),
5094 win_x and win_y are the pointer's position in it
5095 (XTC did this the last time through), and
5096 parent_x and parent_y are the pointer's position in win's parent.
5097 (They are what win_x and win_y were when win was child.
5098 If win is the root window, it has no parent, and
5099 parent_{x,y} are invalid, but that's okay, because we'll
5100 never use them in that case.) */
5102 #ifdef USE_GTK
5103 /* We don't wan't to know the innermost window. We
5104 want the edit window. */
5105 f1 = x_window_to_frame (dpyinfo, win);
5106 #else
5107 /* Is win one of our frames? */
5108 f1 = x_any_window_to_frame (dpyinfo, win);
5109 #endif
5111 #ifdef USE_X_TOOLKIT
5112 /* If we end up with the menu bar window, say it's not
5113 on the frame. */
5114 if (f1 != NULL
5115 && f1->output_data.x->menubar_widget
5116 && win == XtWindow (f1->output_data.x->menubar_widget))
5117 f1 = NULL;
5118 #endif /* USE_X_TOOLKIT */
5121 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
5122 f1 = 0;
5124 x_uncatch_errors_after_check ();
5126 /* If not, is it one of our scroll bars? */
5127 if (! f1)
5129 struct scroll_bar *bar;
5131 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
5133 if (bar)
5135 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5136 win_x = parent_x;
5137 win_y = parent_y;
5141 if (f1 == 0 && insist > 0)
5142 f1 = SELECTED_FRAME ();
5144 if (f1)
5146 /* Ok, we found a frame. Store all the values.
5147 last_mouse_glyph is a rectangle used to reduce the
5148 generation of mouse events. To not miss any motion
5149 events, we must divide the frame into rectangles of the
5150 size of the smallest character that could be displayed
5151 on it, i.e. into the same rectangles that matrices on
5152 the frame are divided into. */
5154 /* FIXME: what if F1 is not an X frame? */
5155 dpyinfo = FRAME_DISPLAY_INFO (f1);
5156 remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
5157 dpyinfo->last_mouse_glyph_frame = f1;
5159 *bar_window = Qnil;
5160 *part = 0;
5161 *fp = f1;
5162 XSETINT (*x, win_x);
5163 XSETINT (*y, win_y);
5164 *timestamp = dpyinfo->last_mouse_movement_time;
5169 unblock_input ();
5174 /***********************************************************************
5175 Scroll bars
5176 ***********************************************************************/
5178 /* Scroll bar support. */
5180 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
5181 manages it.
5182 This can be called in GC, so we have to make sure to strip off mark
5183 bits. */
5185 static struct scroll_bar *
5186 x_window_to_scroll_bar (Display *display, Window window_id, int type)
5188 Lisp_Object tail, frame;
5190 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
5191 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
5192 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
5194 FOR_EACH_FRAME (tail, frame)
5196 Lisp_Object bar, condemned;
5198 if (! FRAME_X_P (XFRAME (frame)))
5199 continue;
5201 /* Scan this frame's scroll bar list for a scroll bar with the
5202 right window ID. */
5203 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
5204 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
5205 /* This trick allows us to search both the ordinary and
5206 condemned scroll bar lists with one loop. */
5207 ! NILP (bar) || (bar = condemned,
5208 condemned = Qnil,
5209 ! NILP (bar));
5210 bar = XSCROLL_BAR (bar)->next)
5211 if (XSCROLL_BAR (bar)->x_window == window_id
5212 && FRAME_X_DISPLAY (XFRAME (frame)) == display
5213 && (type = 2
5214 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
5215 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
5216 return XSCROLL_BAR (bar);
5219 return NULL;
5223 #if defined USE_LUCID
5225 /* Return the Lucid menu bar WINDOW is part of. Return null
5226 if WINDOW is not part of a menu bar. */
5228 static Widget
5229 x_window_to_menu_bar (Window window)
5231 Lisp_Object tail, frame;
5233 FOR_EACH_FRAME (tail, frame)
5234 if (FRAME_X_P (XFRAME (frame)))
5236 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
5238 if (menu_bar && xlwmenu_window_p (menu_bar, window))
5239 return menu_bar;
5241 return NULL;
5244 #endif /* USE_LUCID */
5247 /************************************************************************
5248 Toolkit scroll bars
5249 ************************************************************************/
5251 #ifdef USE_TOOLKIT_SCROLL_BARS
5253 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
5254 int, int, bool);
5256 /* Lisp window being scrolled. Set when starting to interact with
5257 a toolkit scroll bar, reset to nil when ending the interaction. */
5259 static Lisp_Object window_being_scrolled;
5261 /* Whether this is an Xaw with arrow-scrollbars. This should imply
5262 that movements of 1/20 of the screen size are mapped to up/down. */
5264 #ifndef USE_GTK
5265 /* Id of action hook installed for scroll bars. */
5267 static XtActionHookId action_hook_id;
5268 static XtActionHookId horizontal_action_hook_id;
5270 static Boolean xaw3d_arrow_scroll;
5272 /* Whether the drag scrolling maintains the mouse at the top of the
5273 thumb. If not, resizing the thumb needs to be done more carefully
5274 to avoid jerkiness. */
5276 static Boolean xaw3d_pick_top;
5278 /* Action hook installed via XtAppAddActionHook when toolkit scroll
5279 bars are used.. The hook is responsible for detecting when
5280 the user ends an interaction with the scroll bar, and generates
5281 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
5283 static void
5284 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
5285 XEvent *event, String *params, Cardinal *num_params)
5287 bool scroll_bar_p;
5288 const char *end_action;
5290 #ifdef USE_MOTIF
5291 scroll_bar_p = XmIsScrollBar (widget);
5292 end_action = "Release";
5293 #else /* !USE_MOTIF i.e. use Xaw */
5294 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
5295 end_action = "EndScroll";
5296 #endif /* USE_MOTIF */
5298 if (scroll_bar_p
5299 && strcmp (action_name, end_action) == 0
5300 && WINDOWP (window_being_scrolled))
5302 struct window *w;
5303 struct scroll_bar *bar;
5305 x_send_scroll_bar_event (window_being_scrolled,
5306 scroll_bar_end_scroll, 0, 0, false);
5307 w = XWINDOW (window_being_scrolled);
5308 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5310 if (bar->dragging != -1)
5312 bar->dragging = -1;
5313 /* The thumb size is incorrect while dragging: fix it. */
5314 set_vertical_scroll_bar (w);
5316 window_being_scrolled = Qnil;
5317 #if defined (USE_LUCID)
5318 bar->last_seen_part = scroll_bar_nowhere;
5319 #endif
5320 /* Xt timeouts no longer needed. */
5321 toolkit_scroll_bar_interaction = false;
5326 static void
5327 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
5328 XEvent *event, String *params, Cardinal *num_params)
5330 bool scroll_bar_p;
5331 const char *end_action;
5333 #ifdef USE_MOTIF
5334 scroll_bar_p = XmIsScrollBar (widget);
5335 end_action = "Release";
5336 #else /* !USE_MOTIF i.e. use Xaw */
5337 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
5338 end_action = "EndScroll";
5339 #endif /* USE_MOTIF */
5341 if (scroll_bar_p
5342 && strcmp (action_name, end_action) == 0
5343 && WINDOWP (window_being_scrolled))
5345 struct window *w;
5346 struct scroll_bar *bar;
5348 x_send_scroll_bar_event (window_being_scrolled,
5349 scroll_bar_end_scroll, 0, 0, true);
5350 w = XWINDOW (window_being_scrolled);
5351 if (!NILP (w->horizontal_scroll_bar))
5353 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
5354 if (bar->dragging != -1)
5356 bar->dragging = -1;
5357 /* The thumb size is incorrect while dragging: fix it. */
5358 set_horizontal_scroll_bar (w);
5360 window_being_scrolled = Qnil;
5361 #if defined (USE_LUCID)
5362 bar->last_seen_part = scroll_bar_nowhere;
5363 #endif
5364 /* Xt timeouts no longer needed. */
5365 toolkit_scroll_bar_interaction = false;
5369 #endif /* not USE_GTK */
5371 /* Send a client message with message type Xatom_Scrollbar for a
5372 scroll action to the frame of WINDOW. PART is a value identifying
5373 the part of the scroll bar that was clicked on. PORTION is the
5374 amount to scroll of a whole of WHOLE. */
5376 static void
5377 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
5378 int portion, int whole, bool horizontal)
5380 XEvent event;
5381 XClientMessageEvent *ev = &event.xclient;
5382 struct window *w = XWINDOW (window);
5383 struct frame *f = XFRAME (w->frame);
5384 intptr_t iw = (intptr_t) w;
5385 verify (INTPTR_WIDTH <= 64);
5386 int sign_shift = INTPTR_WIDTH - 32;
5388 block_input ();
5390 /* Construct a ClientMessage event to send to the frame. */
5391 ev->type = ClientMessage;
5392 ev->message_type = (horizontal
5393 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
5394 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
5395 ev->display = FRAME_X_DISPLAY (f);
5396 ev->window = FRAME_X_WINDOW (f);
5397 ev->format = 32;
5399 /* A 32-bit X client on a 64-bit X server can pass a window pointer
5400 as-is. A 64-bit client on a 32-bit X server is in trouble
5401 because a pointer does not fit and would be truncated while
5402 passing through the server. So use two slots and hope that X12
5403 will resolve such issues someday. */
5404 ev->data.l[0] = iw >> 31 >> 1;
5405 ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
5406 ev->data.l[2] = part;
5407 ev->data.l[3] = portion;
5408 ev->data.l[4] = whole;
5410 /* Make Xt timeouts work while the scroll bar is active. */
5411 #ifdef USE_X_TOOLKIT
5412 toolkit_scroll_bar_interaction = true;
5413 x_activate_timeout_atimer ();
5414 #endif
5416 /* Setting the event mask to zero means that the message will
5417 be sent to the client that created the window, and if that
5418 window no longer exists, no event will be sent. */
5419 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
5420 unblock_input ();
5424 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
5425 in *IEVENT. */
5427 static void
5428 x_scroll_bar_to_input_event (const XEvent *event,
5429 struct input_event *ievent)
5431 const XClientMessageEvent *ev = &event->xclient;
5432 Lisp_Object window;
5433 struct window *w;
5435 /* See the comment in the function above. */
5436 intptr_t iw0 = ev->data.l[0];
5437 intptr_t iw1 = ev->data.l[1];
5438 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
5439 w = (struct window *) iw;
5441 XSETWINDOW (window, w);
5443 ievent->kind = SCROLL_BAR_CLICK_EVENT;
5444 ievent->frame_or_window = window;
5445 ievent->arg = Qnil;
5446 #ifdef USE_GTK
5447 ievent->timestamp = CurrentTime;
5448 #else
5449 ievent->timestamp =
5450 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
5451 #endif
5452 ievent->code = 0;
5453 ievent->part = ev->data.l[2];
5454 ievent->x = make_number (ev->data.l[3]);
5455 ievent->y = make_number (ev->data.l[4]);
5456 ievent->modifiers = 0;
5459 /* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
5460 input event in *IEVENT. */
5462 static void
5463 x_horizontal_scroll_bar_to_input_event (const XEvent *event,
5464 struct input_event *ievent)
5466 const XClientMessageEvent *ev = &event->xclient;
5467 Lisp_Object window;
5468 struct window *w;
5470 /* See the comment in the function above. */
5471 intptr_t iw0 = ev->data.l[0];
5472 intptr_t iw1 = ev->data.l[1];
5473 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
5474 w = (struct window *) iw;
5476 XSETWINDOW (window, w);
5478 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
5479 ievent->frame_or_window = window;
5480 ievent->arg = Qnil;
5481 #ifdef USE_GTK
5482 ievent->timestamp = CurrentTime;
5483 #else
5484 ievent->timestamp =
5485 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
5486 #endif
5487 ievent->code = 0;
5488 ievent->part = ev->data.l[2];
5489 ievent->x = make_number (ev->data.l[3]);
5490 ievent->y = make_number (ev->data.l[4]);
5491 ievent->modifiers = 0;
5495 #ifdef USE_MOTIF
5497 /* Minimum and maximum values used for Motif scroll bars. */
5499 #define XM_SB_MAX 10000000
5501 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
5502 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
5503 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
5505 static void
5506 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5508 struct scroll_bar *bar = client_data;
5509 XmScrollBarCallbackStruct *cs = call_data;
5510 enum scroll_bar_part part = scroll_bar_nowhere;
5511 bool horizontal = bar->horizontal;
5512 int whole = 0, portion = 0;
5514 switch (cs->reason)
5516 case XmCR_DECREMENT:
5517 bar->dragging = -1;
5518 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
5519 break;
5521 case XmCR_INCREMENT:
5522 bar->dragging = -1;
5523 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
5524 break;
5526 case XmCR_PAGE_DECREMENT:
5527 bar->dragging = -1;
5528 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
5529 break;
5531 case XmCR_PAGE_INCREMENT:
5532 bar->dragging = -1;
5533 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
5534 break;
5536 case XmCR_TO_TOP:
5537 bar->dragging = -1;
5538 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
5539 break;
5541 case XmCR_TO_BOTTOM:
5542 bar->dragging = -1;
5543 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
5544 break;
5546 case XmCR_DRAG:
5548 int slider_size;
5550 block_input ();
5551 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
5552 unblock_input ();
5554 if (horizontal)
5556 portion = bar->whole * ((float)cs->value / XM_SB_MAX);
5557 whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
5558 portion = min (portion, whole);
5559 part = scroll_bar_horizontal_handle;
5561 else
5563 whole = XM_SB_MAX - slider_size;
5564 portion = min (cs->value, whole);
5565 part = scroll_bar_handle;
5568 bar->dragging = cs->value;
5570 break;
5572 case XmCR_VALUE_CHANGED:
5573 break;
5576 if (part != scroll_bar_nowhere)
5578 window_being_scrolled = bar->window;
5579 x_send_scroll_bar_event (bar->window, part, portion, whole,
5580 bar->horizontal);
5584 #elif defined USE_GTK
5586 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
5587 bar widget. DATA is a pointer to the scroll_bar structure. */
5589 static gboolean
5590 xg_scroll_callback (GtkRange *range,
5591 GtkScrollType scroll,
5592 gdouble value,
5593 gpointer user_data)
5595 int whole = 0, portion = 0;
5596 struct scroll_bar *bar = user_data;
5597 enum scroll_bar_part part = scroll_bar_nowhere;
5598 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
5599 struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
5601 if (xg_ignore_gtk_scrollbar) return false;
5603 switch (scroll)
5605 case GTK_SCROLL_JUMP:
5606 /* Buttons 1 2 or 3 must be grabbed. */
5607 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
5608 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
5610 if (bar->horizontal)
5612 part = scroll_bar_horizontal_handle;
5613 whole = (int)(gtk_adjustment_get_upper (adj) -
5614 gtk_adjustment_get_page_size (adj));
5615 portion = min ((int)value, whole);
5616 bar->dragging = portion;
5618 else
5620 part = scroll_bar_handle;
5621 whole = gtk_adjustment_get_upper (adj) -
5622 gtk_adjustment_get_page_size (adj);
5623 portion = min ((int)value, whole);
5624 bar->dragging = portion;
5627 break;
5628 case GTK_SCROLL_STEP_BACKWARD:
5629 part = (bar->horizontal
5630 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
5631 bar->dragging = -1;
5632 break;
5633 case GTK_SCROLL_STEP_FORWARD:
5634 part = (bar->horizontal
5635 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
5636 bar->dragging = -1;
5637 break;
5638 case GTK_SCROLL_PAGE_BACKWARD:
5639 part = (bar->horizontal
5640 ? scroll_bar_before_handle : scroll_bar_above_handle);
5641 bar->dragging = -1;
5642 break;
5643 case GTK_SCROLL_PAGE_FORWARD:
5644 part = (bar->horizontal
5645 ? scroll_bar_after_handle : scroll_bar_below_handle);
5646 bar->dragging = -1;
5647 break;
5648 default:
5649 break;
5652 if (part != scroll_bar_nowhere)
5654 window_being_scrolled = bar->window;
5655 x_send_scroll_bar_event (bar->window, part, portion, whole,
5656 bar->horizontal);
5659 return false;
5662 /* Callback for button release. Sets dragging to -1 when dragging is done. */
5664 static gboolean
5665 xg_end_scroll_callback (GtkWidget *widget,
5666 GdkEventButton *event,
5667 gpointer user_data)
5669 struct scroll_bar *bar = user_data;
5670 bar->dragging = -1;
5671 if (WINDOWP (window_being_scrolled))
5673 x_send_scroll_bar_event (window_being_scrolled,
5674 scroll_bar_end_scroll, 0, 0, bar->horizontal);
5675 window_being_scrolled = Qnil;
5678 return false;
5682 #else /* not USE_GTK and not USE_MOTIF */
5684 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
5685 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
5686 scroll bar struct. CALL_DATA is a pointer to a float saying where
5687 the thumb is. */
5689 static void
5690 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5692 struct scroll_bar *bar = client_data;
5693 float *top_addr = call_data;
5694 float top = *top_addr;
5695 float shown;
5696 int whole, portion, height, width;
5697 enum scroll_bar_part part;
5698 bool horizontal = bar->horizontal;
5701 if (horizontal)
5703 /* Get the size of the thumb, a value between 0 and 1. */
5704 block_input ();
5705 XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
5706 unblock_input ();
5708 if (shown < 1)
5710 whole = bar->whole - (shown * bar->whole);
5711 portion = min (top * bar->whole, whole);
5713 else
5715 whole = bar->whole;
5716 portion = 0;
5719 part = scroll_bar_horizontal_handle;
5721 else
5723 /* Get the size of the thumb, a value between 0 and 1. */
5724 block_input ();
5725 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
5726 unblock_input ();
5728 whole = 10000000;
5729 portion = shown < 1 ? top * whole : 0;
5731 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
5732 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
5733 the bottom, so we force the scrolling whenever we see that we're
5734 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
5735 we try to ensure that we always stay two pixels away from the
5736 bottom). */
5737 part = scroll_bar_down_arrow;
5738 else
5739 part = scroll_bar_handle;
5742 window_being_scrolled = bar->window;
5743 bar->dragging = portion;
5744 bar->last_seen_part = part;
5745 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
5749 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
5750 i.e. line or page up or down. WIDGET is the Xaw scroll bar
5751 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
5752 the scroll bar. CALL_DATA is an integer specifying the action that
5753 has taken place. Its magnitude is in the range 0..height of the
5754 scroll bar. Negative values mean scroll towards buffer start.
5755 Values < height of scroll bar mean line-wise movement. */
5757 static void
5758 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
5760 struct scroll_bar *bar = client_data;
5761 /* The position really is stored cast to a pointer. */
5762 int position = (intptr_t) call_data;
5763 Dimension height, width;
5764 enum scroll_bar_part part;
5766 if (bar->horizontal)
5768 /* Get the width of the scroll bar. */
5769 block_input ();
5770 XtVaGetValues (widget, XtNwidth, &width, NULL);
5771 unblock_input ();
5773 if (eabs (position) >= width)
5774 part = (position < 0) ? scroll_bar_before_handle : scroll_bar_after_handle;
5776 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
5777 it maps line-movement to call_data = max(5, height/20). */
5778 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, width / 20))
5779 part = (position < 0) ? scroll_bar_left_arrow : scroll_bar_right_arrow;
5780 else
5781 part = scroll_bar_move_ratio;
5783 window_being_scrolled = bar->window;
5784 bar->dragging = -1;
5785 bar->last_seen_part = part;
5786 x_send_scroll_bar_event (bar->window, part, position, width,
5787 bar->horizontal);
5789 else
5792 /* Get the height of the scroll bar. */
5793 block_input ();
5794 XtVaGetValues (widget, XtNheight, &height, NULL);
5795 unblock_input ();
5797 if (eabs (position) >= height)
5798 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
5800 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
5801 it maps line-movement to call_data = max(5, height/20). */
5802 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
5803 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
5804 else
5805 part = scroll_bar_move_ratio;
5807 window_being_scrolled = bar->window;
5808 bar->dragging = -1;
5809 bar->last_seen_part = part;
5810 x_send_scroll_bar_event (bar->window, part, position, height,
5811 bar->horizontal);
5815 #endif /* not USE_GTK and not USE_MOTIF */
5817 #define SCROLL_BAR_NAME "verticalScrollBar"
5818 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
5820 /* Create the widget for scroll bar BAR on frame F. Record the widget
5821 and X window of the scroll bar in BAR. */
5823 #ifdef USE_GTK
5824 static void
5825 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
5827 const char *scroll_bar_name = SCROLL_BAR_NAME;
5829 block_input ();
5830 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
5831 G_CALLBACK (xg_end_scroll_callback),
5832 scroll_bar_name);
5833 unblock_input ();
5836 static void
5837 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
5839 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
5841 block_input ();
5842 xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
5843 G_CALLBACK (xg_end_scroll_callback),
5844 scroll_bar_name);
5845 unblock_input ();
5848 #else /* not USE_GTK */
5850 static void
5851 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
5853 Window xwindow;
5854 Widget widget;
5855 Arg av[20];
5856 int ac = 0;
5857 const char *scroll_bar_name = SCROLL_BAR_NAME;
5858 unsigned long pixel;
5860 block_input ();
5862 #ifdef USE_MOTIF
5863 /* Set resources. Create the widget. */
5864 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
5865 XtSetArg (av[ac], XmNminimum, 0); ++ac;
5866 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
5867 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
5868 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
5869 XtSetArg (av[ac], XmNincrement, 1); ++ac;
5870 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
5872 pixel = f->output_data.x->scroll_bar_foreground_pixel;
5873 if (pixel != -1)
5875 XtSetArg (av[ac], XmNforeground, pixel);
5876 ++ac;
5879 pixel = f->output_data.x->scroll_bar_background_pixel;
5880 if (pixel != -1)
5882 XtSetArg (av[ac], XmNbackground, pixel);
5883 ++ac;
5886 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
5887 (char *) scroll_bar_name, av, ac);
5889 /* Add one callback for everything that can happen. */
5890 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
5891 (XtPointer) bar);
5892 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
5893 (XtPointer) bar);
5894 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
5895 (XtPointer) bar);
5896 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
5897 (XtPointer) bar);
5898 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
5899 (XtPointer) bar);
5900 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
5901 (XtPointer) bar);
5902 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
5903 (XtPointer) bar);
5905 /* Realize the widget. Only after that is the X window created. */
5906 XtRealizeWidget (widget);
5908 /* Set the cursor to an arrow. I didn't find a resource to do that.
5909 And I'm wondering why it hasn't an arrow cursor by default. */
5910 XDefineCursor (XtDisplay (widget), XtWindow (widget),
5911 f->output_data.x->nontext_cursor);
5913 #else /* !USE_MOTIF i.e. use Xaw */
5915 /* Set resources. Create the widget. The background of the
5916 Xaw3d scroll bar widget is a little bit light for my taste.
5917 We don't alter it here to let users change it according
5918 to their taste with `emacs*verticalScrollBar.background: xxx'. */
5919 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
5920 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
5921 /* For smoother scrolling with Xaw3d -sm */
5922 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
5924 pixel = f->output_data.x->scroll_bar_foreground_pixel;
5925 if (pixel != -1)
5927 XtSetArg (av[ac], XtNforeground, pixel);
5928 ++ac;
5931 pixel = f->output_data.x->scroll_bar_background_pixel;
5932 if (pixel != -1)
5934 XtSetArg (av[ac], XtNbackground, pixel);
5935 ++ac;
5938 /* Top/bottom shadow colors. */
5940 /* Allocate them, if necessary. */
5941 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
5943 pixel = f->output_data.x->scroll_bar_background_pixel;
5944 if (pixel != -1)
5946 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
5947 FRAME_X_COLORMAP (f),
5948 &pixel, 1.2, 0x8000))
5949 pixel = -1;
5950 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
5953 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
5955 pixel = f->output_data.x->scroll_bar_background_pixel;
5956 if (pixel != -1)
5958 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
5959 FRAME_X_COLORMAP (f),
5960 &pixel, 0.6, 0x4000))
5961 pixel = -1;
5962 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
5966 #ifdef XtNbeNiceToColormap
5967 /* Tell the toolkit about them. */
5968 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
5969 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
5970 /* We tried to allocate a color for the top/bottom shadow, and
5971 failed, so tell Xaw3d to use dithering instead. */
5972 /* But only if we have a small colormap. Xaw3d can allocate nice
5973 colors itself. */
5975 XtSetArg (av[ac], XtNbeNiceToColormap,
5976 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
5977 ++ac;
5979 else
5980 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
5981 be more consistent with other emacs 3d colors, and since Xaw3d is
5982 not good at dealing with allocation failure. */
5984 /* This tells Xaw3d to use real colors instead of dithering for
5985 the shadows. */
5986 XtSetArg (av[ac], XtNbeNiceToColormap, False);
5987 ++ac;
5989 /* Specify the colors. */
5990 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
5991 if (pixel != -1)
5993 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
5994 ++ac;
5996 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
5997 if (pixel != -1)
5999 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
6000 ++ac;
6003 #endif
6005 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
6006 f->output_data.x->edit_widget, av, ac);
6009 char const *initial = "";
6010 char const *val = initial;
6011 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
6012 #ifdef XtNarrowScrollbars
6013 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
6014 #endif
6015 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
6016 if (xaw3d_arrow_scroll || val == initial)
6017 { /* ARROW_SCROLL */
6018 xaw3d_arrow_scroll = True;
6019 /* Isn't that just a personal preference ? --Stef */
6020 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
6024 /* Define callbacks. */
6025 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
6026 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
6027 (XtPointer) bar);
6029 /* Realize the widget. Only after that is the X window created. */
6030 XtRealizeWidget (widget);
6032 #endif /* !USE_MOTIF */
6034 /* Install an action hook that lets us detect when the user
6035 finishes interacting with a scroll bar. */
6036 if (action_hook_id == 0)
6037 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
6039 /* Remember X window and widget in the scroll bar vector. */
6040 SET_SCROLL_BAR_X_WIDGET (bar, widget);
6041 xwindow = XtWindow (widget);
6042 bar->x_window = xwindow;
6043 bar->whole = 1;
6044 bar->horizontal = false;
6046 unblock_input ();
6049 static void
6050 x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
6052 Window xwindow;
6053 Widget widget;
6054 Arg av[20];
6055 int ac = 0;
6056 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
6057 unsigned long pixel;
6059 block_input ();
6061 #ifdef USE_MOTIF
6062 /* Set resources. Create the widget. */
6063 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6064 XtSetArg (av[ac], XmNminimum, 0); ++ac;
6065 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
6066 XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
6067 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
6068 XtSetArg (av[ac], XmNincrement, 1); ++ac;
6069 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
6071 pixel = f->output_data.x->scroll_bar_foreground_pixel;
6072 if (pixel != -1)
6074 XtSetArg (av[ac], XmNforeground, pixel);
6075 ++ac;
6078 pixel = f->output_data.x->scroll_bar_background_pixel;
6079 if (pixel != -1)
6081 XtSetArg (av[ac], XmNbackground, pixel);
6082 ++ac;
6085 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
6086 (char *) scroll_bar_name, av, ac);
6088 /* Add one callback for everything that can happen. */
6089 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
6090 (XtPointer) bar);
6091 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
6092 (XtPointer) bar);
6093 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
6094 (XtPointer) bar);
6095 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
6096 (XtPointer) bar);
6097 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
6098 (XtPointer) bar);
6099 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
6100 (XtPointer) bar);
6101 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
6102 (XtPointer) bar);
6104 /* Realize the widget. Only after that is the X window created. */
6105 XtRealizeWidget (widget);
6107 /* Set the cursor to an arrow. I didn't find a resource to do that.
6108 And I'm wondering why it hasn't an arrow cursor by default. */
6109 XDefineCursor (XtDisplay (widget), XtWindow (widget),
6110 f->output_data.x->nontext_cursor);
6112 #else /* !USE_MOTIF i.e. use Xaw */
6114 /* Set resources. Create the widget. The background of the
6115 Xaw3d scroll bar widget is a little bit light for my taste.
6116 We don't alter it here to let users change it according
6117 to their taste with `emacs*verticalScrollBar.background: xxx'. */
6118 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
6119 XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
6120 /* For smoother scrolling with Xaw3d -sm */
6121 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
6123 pixel = f->output_data.x->scroll_bar_foreground_pixel;
6124 if (pixel != -1)
6126 XtSetArg (av[ac], XtNforeground, pixel);
6127 ++ac;
6130 pixel = f->output_data.x->scroll_bar_background_pixel;
6131 if (pixel != -1)
6133 XtSetArg (av[ac], XtNbackground, pixel);
6134 ++ac;
6137 /* Top/bottom shadow colors. */
6139 /* Allocate them, if necessary. */
6140 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
6142 pixel = f->output_data.x->scroll_bar_background_pixel;
6143 if (pixel != -1)
6145 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6146 FRAME_X_COLORMAP (f),
6147 &pixel, 1.2, 0x8000))
6148 pixel = -1;
6149 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
6152 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6154 pixel = f->output_data.x->scroll_bar_background_pixel;
6155 if (pixel != -1)
6157 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
6158 FRAME_X_COLORMAP (f),
6159 &pixel, 0.6, 0x4000))
6160 pixel = -1;
6161 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
6165 #ifdef XtNbeNiceToColormap
6166 /* Tell the toolkit about them. */
6167 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
6168 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
6169 /* We tried to allocate a color for the top/bottom shadow, and
6170 failed, so tell Xaw3d to use dithering instead. */
6171 /* But only if we have a small colormap. Xaw3d can allocate nice
6172 colors itself. */
6174 XtSetArg (av[ac], XtNbeNiceToColormap,
6175 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
6176 ++ac;
6178 else
6179 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
6180 be more consistent with other emacs 3d colors, and since Xaw3d is
6181 not good at dealing with allocation failure. */
6183 /* This tells Xaw3d to use real colors instead of dithering for
6184 the shadows. */
6185 XtSetArg (av[ac], XtNbeNiceToColormap, False);
6186 ++ac;
6188 /* Specify the colors. */
6189 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
6190 if (pixel != -1)
6192 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
6193 ++ac;
6195 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
6196 if (pixel != -1)
6198 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
6199 ++ac;
6202 #endif
6204 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
6205 f->output_data.x->edit_widget, av, ac);
6208 char const *initial = "";
6209 char const *val = initial;
6210 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
6211 #ifdef XtNarrowScrollbars
6212 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
6213 #endif
6214 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
6215 if (xaw3d_arrow_scroll || val == initial)
6216 { /* ARROW_SCROLL */
6217 xaw3d_arrow_scroll = True;
6218 /* Isn't that just a personal preference ? --Stef */
6219 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
6223 /* Define callbacks. */
6224 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
6225 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
6226 (XtPointer) bar);
6228 /* Realize the widget. Only after that is the X window created. */
6229 XtRealizeWidget (widget);
6231 #endif /* !USE_MOTIF */
6233 /* Install an action hook that lets us detect when the user
6234 finishes interacting with a scroll bar. */
6235 if (horizontal_action_hook_id == 0)
6236 horizontal_action_hook_id
6237 = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
6239 /* Remember X window and widget in the scroll bar vector. */
6240 SET_SCROLL_BAR_X_WIDGET (bar, widget);
6241 xwindow = XtWindow (widget);
6242 bar->x_window = xwindow;
6243 bar->whole = 1;
6244 bar->horizontal = true;
6246 unblock_input ();
6248 #endif /* not USE_GTK */
6251 /* Set the thumb size and position of scroll bar BAR. We are currently
6252 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6254 #ifdef USE_GTK
6255 static void
6256 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
6258 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
6261 static void
6262 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
6264 xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
6267 #else /* not USE_GTK */
6268 static void
6269 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
6270 int whole)
6272 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6273 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6274 float top, shown;
6276 block_input ();
6278 #ifdef USE_MOTIF
6280 if (scroll_bar_adjust_thumb_portion_p)
6282 /* We use an estimate of 30 chars per line rather than the real
6283 `portion' value. This has the disadvantage that the thumb size
6284 is not very representative, but it makes our life a lot easier.
6285 Otherwise, we have to constantly adjust the thumb size, which
6286 we can't always do quickly enough: while dragging, the size of
6287 the thumb might prevent the user from dragging the thumb all the
6288 way to the end. but Motif and some versions of Xaw3d don't allow
6289 updating the thumb size while dragging. Also, even if we can update
6290 its size, the update will often happen too late.
6291 If you don't believe it, check out revision 1.650 of xterm.c to see
6292 what hoops we were going through and the still poor behavior we got. */
6293 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
6294 /* When the thumb is at the bottom, position == whole.
6295 So we need to increase `whole' to make space for the thumb. */
6296 whole += portion;
6299 if (whole <= 0)
6300 top = 0, shown = 1;
6301 else
6303 top = (float) position / whole;
6304 shown = (float) portion / whole;
6307 if (bar->dragging == -1)
6309 int size, value;
6311 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
6312 is the scroll bar's maximum and MIN is the scroll bar's minimum
6313 value. */
6314 size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
6316 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
6317 value = top * XM_SB_MAX;
6318 value = min (value, XM_SB_MAX - size);
6320 XmScrollBarSetValues (widget, value, size, 0, 0, False);
6322 #else /* !USE_MOTIF i.e. use Xaw */
6324 if (whole == 0)
6325 top = 0, shown = 1;
6326 else
6328 top = (float) position / whole;
6329 shown = (float) portion / whole;
6333 float old_top, old_shown;
6334 Dimension height;
6335 XtVaGetValues (widget,
6336 XtNtopOfThumb, &old_top,
6337 XtNshown, &old_shown,
6338 XtNheight, &height,
6339 NULL);
6341 /* Massage the top+shown values. */
6342 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
6343 top = max (0, min (1, top));
6344 else
6345 top = old_top;
6346 #if ! defined (HAVE_XAW3D)
6347 /* With Xaw, 'top' values too closer to 1.0 may
6348 cause the thumb to disappear. Fix that. */
6349 top = min (top, 0.99f);
6350 #endif
6351 /* Keep two pixels available for moving the thumb down. */
6352 shown = max (0, min (1 - top - (2.0f / height), shown));
6353 #if ! defined (HAVE_XAW3D)
6354 /* Likewise with too small 'shown'. */
6355 shown = max (shown, 0.01f);
6356 #endif
6358 /* If the call to XawScrollbarSetThumb below doesn't seem to
6359 work, check that 'NARROWPROTO' is defined in src/config.h.
6360 If this is not so, most likely you need to fix configure. */
6361 if (top != old_top || shown != old_shown)
6363 if (bar->dragging == -1)
6364 XawScrollbarSetThumb (widget, top, shown);
6365 else
6367 /* Try to make the scrolling a tad smoother. */
6368 if (!xaw3d_pick_top)
6369 shown = min (shown, old_shown);
6371 XawScrollbarSetThumb (widget, top, shown);
6375 #endif /* !USE_MOTIF */
6377 unblock_input ();
6380 static void
6381 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
6382 int whole)
6384 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6385 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6386 float top, shown;
6388 block_input ();
6390 #ifdef USE_MOTIF
6391 bar->whole = whole;
6392 shown = (float) portion / whole;
6393 top = (float) position / (whole - portion);
6395 int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
6396 int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
6398 XmScrollBarSetValues (widget, value, size, 0, 0, False);
6400 #else /* !USE_MOTIF i.e. use Xaw */
6401 bar->whole = whole;
6402 if (whole == 0)
6403 top = 0, shown = 1;
6404 else
6406 top = (float) position / whole;
6407 shown = (float) portion / whole;
6411 float old_top, old_shown;
6412 Dimension height;
6413 XtVaGetValues (widget,
6414 XtNtopOfThumb, &old_top,
6415 XtNshown, &old_shown,
6416 XtNheight, &height,
6417 NULL);
6419 #if false
6420 /* Massage the top+shown values. */
6421 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
6422 top = max (0, min (1, top));
6423 else
6424 top = old_top;
6425 #if ! defined (HAVE_XAW3D)
6426 /* With Xaw, 'top' values too closer to 1.0 may
6427 cause the thumb to disappear. Fix that. */
6428 top = min (top, 0.99f);
6429 #endif
6430 /* Keep two pixels available for moving the thumb down. */
6431 shown = max (0, min (1 - top - (2.0f / height), shown));
6432 #if ! defined (HAVE_XAW3D)
6433 /* Likewise with too small 'shown'. */
6434 shown = max (shown, 0.01f);
6435 #endif
6436 #endif
6438 /* If the call to XawScrollbarSetThumb below doesn't seem to
6439 work, check that 'NARROWPROTO' is defined in src/config.h.
6440 If this is not so, most likely you need to fix configure. */
6441 XawScrollbarSetThumb (widget, top, shown);
6442 #if false
6443 if (top != old_top || shown != old_shown)
6445 if (bar->dragging == -1)
6446 XawScrollbarSetThumb (widget, top, shown);
6447 else
6449 /* Try to make the scrolling a tad smoother. */
6450 if (!xaw3d_pick_top)
6451 shown = min (shown, old_shown);
6453 XawScrollbarSetThumb (widget, top, shown);
6456 #endif
6458 #endif /* !USE_MOTIF */
6460 unblock_input ();
6462 #endif /* not USE_GTK */
6464 #endif /* USE_TOOLKIT_SCROLL_BARS */
6468 /************************************************************************
6469 Scroll bars, general
6470 ************************************************************************/
6472 /* Create a scroll bar and return the scroll bar vector for it. W is
6473 the Emacs window on which to create the scroll bar. TOP, LEFT,
6474 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
6475 scroll bar. */
6477 static struct scroll_bar *
6478 x_scroll_bar_create (struct window *w, int top, int left,
6479 int width, int height, bool horizontal)
6481 struct frame *f = XFRAME (w->frame);
6482 struct scroll_bar *bar
6483 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
6484 Lisp_Object barobj;
6486 block_input ();
6488 #ifdef USE_TOOLKIT_SCROLL_BARS
6489 if (horizontal)
6490 x_create_horizontal_toolkit_scroll_bar (f, bar);
6491 else
6492 x_create_toolkit_scroll_bar (f, bar);
6493 #else /* not USE_TOOLKIT_SCROLL_BARS */
6495 XSetWindowAttributes a;
6496 unsigned long mask;
6497 Window window;
6499 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
6500 if (a.background_pixel == -1)
6501 a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
6503 a.event_mask = (ButtonPressMask | ButtonReleaseMask
6504 | ButtonMotionMask | PointerMotionHintMask
6505 | ExposureMask);
6506 a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
6508 mask = (CWBackPixel | CWEventMask | CWCursor);
6510 /* Clear the area of W that will serve as a scroll bar. This is
6511 for the case that a window has been split horizontally. In
6512 this case, no clear_frame is generated to reduce flickering. */
6513 if (width > 0 && window_box_height (w) > 0)
6514 x_clear_area (f, left, top, width, window_box_height (w));
6516 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6517 /* Position and size of scroll bar. */
6518 left, top, width, height,
6519 /* Border width, depth, class, and visual. */
6521 CopyFromParent,
6522 CopyFromParent,
6523 CopyFromParent,
6524 /* Attributes. */
6525 mask, &a);
6526 bar->x_window = window;
6528 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6530 XSETWINDOW (bar->window, w);
6531 bar->top = top;
6532 bar->left = left;
6533 bar->width = width;
6534 bar->height = height;
6535 bar->start = 0;
6536 bar->end = 0;
6537 bar->dragging = -1;
6538 bar->horizontal = horizontal;
6539 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
6540 bar->last_seen_part = scroll_bar_nowhere;
6541 #endif
6543 /* Add bar to its frame's list of scroll bars. */
6544 bar->next = FRAME_SCROLL_BARS (f);
6545 bar->prev = Qnil;
6546 XSETVECTOR (barobj, bar);
6547 fset_scroll_bars (f, barobj);
6548 if (!NILP (bar->next))
6549 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
6551 /* Map the window/widget. */
6552 #ifdef USE_TOOLKIT_SCROLL_BARS
6554 #ifdef USE_GTK
6555 if (horizontal)
6556 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
6557 left, width, max (height, 1));
6558 else
6559 xg_update_scrollbar_pos (f, bar->x_window, top,
6560 left, width, max (height, 1));
6561 #else /* not USE_GTK */
6562 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6563 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
6564 XtMapWidget (scroll_bar);
6565 /* Don't obscure any child frames. */
6566 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6567 #endif /* not USE_GTK */
6569 #else /* not USE_TOOLKIT_SCROLL_BARS */
6570 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
6571 /* Don't obscure any child frames. */
6572 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6573 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6575 unblock_input ();
6576 return bar;
6580 #ifndef USE_TOOLKIT_SCROLL_BARS
6582 /* Draw BAR's handle in the proper position.
6584 If the handle is already drawn from START to END, don't bother
6585 redrawing it, unless REBUILD; in that case, always
6586 redraw it. (REBUILD is handy for drawing the handle after expose
6587 events.)
6589 Normally, we want to constrain the start and end of the handle to
6590 fit inside its rectangle, but if the user is dragging the scroll
6591 bar handle, we want to let them drag it down all the way, so that
6592 the bar's top is as far down as it goes; otherwise, there's no way
6593 to move to the very end of the buffer. */
6595 static void
6596 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
6597 bool rebuild)
6599 bool dragging = bar->dragging != -1;
6600 Window w = bar->x_window;
6601 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6602 GC gc = f->output_data.x->normal_gc;
6604 /* If the display is already accurate, do nothing. */
6605 if (! rebuild
6606 && start == bar->start
6607 && end == bar->end)
6608 return;
6610 block_input ();
6613 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
6614 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
6615 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
6617 /* Make sure the values are reasonable, and try to preserve
6618 the distance between start and end. */
6620 int length = end - start;
6622 if (start < 0)
6623 start = 0;
6624 else if (start > top_range)
6625 start = top_range;
6626 end = start + length;
6628 if (end < start)
6629 end = start;
6630 else if (end > top_range && ! dragging)
6631 end = top_range;
6634 /* Store the adjusted setting in the scroll bar. */
6635 bar->start = start;
6636 bar->end = end;
6638 /* Clip the end position, just for display. */
6639 if (end > top_range)
6640 end = top_range;
6642 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
6643 below top positions, to make sure the handle is always at least
6644 that many pixels tall. */
6645 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
6647 /* Draw the empty space above the handle. Note that we can't clear
6648 zero-height areas; that means "clear to end of window." */
6649 if ((inside_width > 0) && (start > 0))
6650 x_clear_area1 (FRAME_X_DISPLAY (f), w,
6651 VERTICAL_SCROLL_BAR_LEFT_BORDER,
6652 VERTICAL_SCROLL_BAR_TOP_BORDER,
6653 inside_width, start, False);
6655 /* Change to proper foreground color if one is specified. */
6656 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
6657 XSetForeground (FRAME_X_DISPLAY (f), gc,
6658 f->output_data.x->scroll_bar_foreground_pixel);
6660 /* Draw the handle itself. */
6661 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
6662 /* x, y, width, height */
6663 VERTICAL_SCROLL_BAR_LEFT_BORDER,
6664 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
6665 inside_width, end - start);
6667 /* Restore the foreground color of the GC if we changed it above. */
6668 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
6669 XSetForeground (FRAME_X_DISPLAY (f), gc,
6670 FRAME_FOREGROUND_PIXEL (f));
6672 /* Draw the empty space below the handle. Note that we can't
6673 clear zero-height areas; that means "clear to end of window." */
6674 if ((inside_width > 0) && (end < inside_height))
6675 x_clear_area1 (FRAME_X_DISPLAY (f), w,
6676 VERTICAL_SCROLL_BAR_LEFT_BORDER,
6677 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
6678 inside_width, inside_height - end, False);
6681 unblock_input ();
6684 #endif /* !USE_TOOLKIT_SCROLL_BARS */
6686 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6687 nil. */
6689 static void
6690 x_scroll_bar_remove (struct scroll_bar *bar)
6692 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6693 block_input ();
6695 #ifdef USE_TOOLKIT_SCROLL_BARS
6696 #ifdef USE_GTK
6697 xg_remove_scroll_bar (f, bar->x_window);
6698 #else /* not USE_GTK */
6699 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
6700 #endif /* not USE_GTK */
6701 #else
6702 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
6703 #endif
6705 /* Dissociate this scroll bar from its window. */
6706 if (bar->horizontal)
6707 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
6708 else
6709 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
6711 unblock_input ();
6715 /* Set the handle of the vertical scroll bar for WINDOW to indicate
6716 that we are displaying PORTION characters out of a total of WHOLE
6717 characters, starting at POSITION. If WINDOW has no scroll bar,
6718 create one. */
6720 static void
6721 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
6723 struct frame *f = XFRAME (w->frame);
6724 Lisp_Object barobj;
6725 struct scroll_bar *bar;
6726 int top, height, left, width;
6727 int window_y, window_height;
6729 /* Get window dimensions. */
6730 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
6731 top = window_y;
6732 height = window_height;
6733 left = WINDOW_SCROLL_BAR_AREA_X (w);
6734 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
6736 /* Does the scroll bar exist yet? */
6737 if (NILP (w->vertical_scroll_bar))
6739 if (width > 0 && height > 0)
6741 block_input ();
6742 x_clear_area (f, left, top, width, height);
6743 unblock_input ();
6746 bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
6748 else
6750 /* It may just need to be moved and resized. */
6751 unsigned int mask = 0;
6753 bar = XSCROLL_BAR (w->vertical_scroll_bar);
6755 block_input ();
6757 if (left != bar->left)
6758 mask |= CWX;
6759 if (top != bar->top)
6760 mask |= CWY;
6761 if (width != bar->width)
6762 mask |= CWWidth;
6763 if (height != bar->height)
6764 mask |= CWHeight;
6766 #ifdef USE_TOOLKIT_SCROLL_BARS
6768 /* Move/size the scroll bar widget. */
6769 if (mask)
6771 /* Since toolkit scroll bars are smaller than the space reserved
6772 for them on the frame, we have to clear "under" them. */
6773 if (width > 0 && height > 0)
6774 x_clear_area (f, left, top, width, height);
6775 #ifdef USE_GTK
6776 xg_update_scrollbar_pos (f, bar->x_window, top,
6777 left, width, max (height, 1));
6778 #else /* not USE_GTK */
6779 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
6780 left, top, width, max (height, 1), 0);
6781 #endif /* not USE_GTK */
6783 #else /* not USE_TOOLKIT_SCROLL_BARS */
6785 /* Move/size the scroll bar window. */
6786 if (mask)
6788 XWindowChanges wc;
6790 wc.x = left;
6791 wc.y = top;
6792 wc.width = width;
6793 wc.height = height;
6794 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
6795 mask, &wc);
6798 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6800 /* Remember new settings. */
6801 bar->left = left;
6802 bar->top = top;
6803 bar->width = width;
6804 bar->height = height;
6806 unblock_input ();
6809 #ifdef USE_TOOLKIT_SCROLL_BARS
6810 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
6811 #else /* not USE_TOOLKIT_SCROLL_BARS */
6812 /* Set the scroll bar's current state, unless we're currently being
6813 dragged. */
6814 if (bar->dragging == -1)
6816 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
6818 if (whole == 0)
6819 x_scroll_bar_set_handle (bar, 0, top_range, false);
6820 else
6822 int start = ((double) position * top_range) / whole;
6823 int end = ((double) (position + portion) * top_range) / whole;
6824 x_scroll_bar_set_handle (bar, start, end, false);
6827 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6829 XSETVECTOR (barobj, bar);
6830 wset_vertical_scroll_bar (w, barobj);
6834 static void
6835 XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
6837 struct frame *f = XFRAME (w->frame);
6838 Lisp_Object barobj;
6839 struct scroll_bar *bar;
6840 int top, height, left, width;
6841 int window_x, window_width;
6842 int pixel_width = WINDOW_PIXEL_WIDTH (w);
6844 /* Get window dimensions. */
6845 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
6846 left = window_x;
6847 width = window_width;
6848 top = WINDOW_SCROLL_BAR_AREA_Y (w);
6849 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
6851 /* Does the scroll bar exist yet? */
6852 if (NILP (w->horizontal_scroll_bar))
6854 if (width > 0 && height > 0)
6856 block_input ();
6858 /* Clear also part between window_width and
6859 WINDOW_PIXEL_WIDTH. */
6860 x_clear_area (f, left, top, pixel_width, height);
6861 unblock_input ();
6864 bar = x_scroll_bar_create (w, top, left, width, height, true);
6866 else
6868 /* It may just need to be moved and resized. */
6869 unsigned int mask = 0;
6871 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
6873 block_input ();
6875 if (left != bar->left)
6876 mask |= CWX;
6877 if (top != bar->top)
6878 mask |= CWY;
6879 if (width != bar->width)
6880 mask |= CWWidth;
6881 if (height != bar->height)
6882 mask |= CWHeight;
6884 #ifdef USE_TOOLKIT_SCROLL_BARS
6885 /* Move/size the scroll bar widget. */
6886 if (mask)
6888 /* Since toolkit scroll bars are smaller than the space reserved
6889 for them on the frame, we have to clear "under" them. */
6890 if (width > 0 && height > 0)
6891 x_clear_area (f,
6892 WINDOW_LEFT_EDGE_X (w), top,
6893 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
6894 #ifdef USE_GTK
6895 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
6896 width, height);
6897 #else /* not USE_GTK */
6898 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
6899 left, top, width, height, 0);
6900 #endif /* not USE_GTK */
6902 #else /* not USE_TOOLKIT_SCROLL_BARS */
6904 /* Clear areas not covered by the scroll bar because it's not as
6905 wide as the area reserved for it. This makes sure a
6906 previous mode line display is cleared after C-x 2 C-x 1, for
6907 example. */
6909 int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
6910 int rest = area_height - height;
6911 if (rest > 0 && width > 0)
6912 x_clear_area (f, left, top, width, rest);
6915 /* Move/size the scroll bar window. */
6916 if (mask)
6918 XWindowChanges wc;
6920 wc.x = left;
6921 wc.y = top;
6922 wc.width = width;
6923 wc.height = height;
6924 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
6925 mask, &wc);
6928 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6930 /* Remember new settings. */
6931 bar->left = left;
6932 bar->top = top;
6933 bar->width = width;
6934 bar->height = height;
6936 unblock_input ();
6939 #ifdef USE_TOOLKIT_SCROLL_BARS
6940 x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
6941 #else /* not USE_TOOLKIT_SCROLL_BARS */
6942 /* Set the scroll bar's current state, unless we're currently being
6943 dragged. */
6944 if (bar->dragging == -1)
6946 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
6948 if (whole == 0)
6949 x_scroll_bar_set_handle (bar, 0, left_range, false);
6950 else
6952 int start = ((double) position * left_range) / whole;
6953 int end = ((double) (position + portion) * left_range) / whole;
6954 x_scroll_bar_set_handle (bar, start, end, false);
6957 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6959 XSETVECTOR (barobj, bar);
6960 wset_horizontal_scroll_bar (w, barobj);
6964 /* The following three hooks are used when we're doing a thorough
6965 redisplay of the frame. We don't explicitly know which scroll bars
6966 are going to be deleted, because keeping track of when windows go
6967 away is a real pain - "Can you say set-window-configuration, boys
6968 and girls?" Instead, we just assert at the beginning of redisplay
6969 that *all* scroll bars are to be removed, and then save a scroll bar
6970 from the fiery pit when we actually redisplay its window. */
6972 /* Arrange for all scroll bars on FRAME to be removed at the next call
6973 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
6974 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
6976 static void
6977 XTcondemn_scroll_bars (struct frame *frame)
6979 if (!NILP (FRAME_SCROLL_BARS (frame)))
6981 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
6983 /* Prepend scrollbars to already condemned ones. */
6984 Lisp_Object last = FRAME_SCROLL_BARS (frame);
6986 while (!NILP (XSCROLL_BAR (last)->next))
6987 last = XSCROLL_BAR (last)->next;
6989 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
6990 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
6993 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
6994 fset_scroll_bars (frame, Qnil);
6999 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7000 Note that WINDOW isn't necessarily condemned at all. */
7002 static void
7003 XTredeem_scroll_bar (struct window *w)
7005 struct scroll_bar *bar;
7006 Lisp_Object barobj;
7007 struct frame *f;
7009 /* We can't redeem this window's scroll bar if it doesn't have one. */
7010 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
7011 emacs_abort ();
7013 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
7015 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7016 /* Unlink it from the condemned list. */
7017 f = XFRAME (WINDOW_FRAME (w));
7018 if (NILP (bar->prev))
7020 /* If the prev pointer is nil, it must be the first in one of
7021 the lists. */
7022 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
7023 /* It's not condemned. Everything's fine. */
7024 goto horizontal;
7025 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7026 w->vertical_scroll_bar))
7027 fset_condemned_scroll_bars (f, bar->next);
7028 else
7029 /* If its prev pointer is nil, it must be at the front of
7030 one or the other! */
7031 emacs_abort ();
7033 else
7034 XSCROLL_BAR (bar->prev)->next = bar->next;
7036 if (! NILP (bar->next))
7037 XSCROLL_BAR (bar->next)->prev = bar->prev;
7039 bar->next = FRAME_SCROLL_BARS (f);
7040 bar->prev = Qnil;
7041 XSETVECTOR (barobj, bar);
7042 fset_scroll_bars (f, barobj);
7043 if (! NILP (bar->next))
7044 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7047 horizontal:
7048 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
7050 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
7051 /* Unlink it from the condemned list. */
7052 f = XFRAME (WINDOW_FRAME (w));
7053 if (NILP (bar->prev))
7055 /* If the prev pointer is nil, it must be the first in one of
7056 the lists. */
7057 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
7058 /* It's not condemned. Everything's fine. */
7059 return;
7060 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7061 w->horizontal_scroll_bar))
7062 fset_condemned_scroll_bars (f, bar->next);
7063 else
7064 /* If its prev pointer is nil, it must be at the front of
7065 one or the other! */
7066 emacs_abort ();
7068 else
7069 XSCROLL_BAR (bar->prev)->next = bar->next;
7071 if (! NILP (bar->next))
7072 XSCROLL_BAR (bar->next)->prev = bar->prev;
7074 bar->next = FRAME_SCROLL_BARS (f);
7075 bar->prev = Qnil;
7076 XSETVECTOR (barobj, bar);
7077 fset_scroll_bars (f, barobj);
7078 if (! NILP (bar->next))
7079 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7083 /* Remove all scroll bars on FRAME that haven't been saved since the
7084 last call to `*condemn_scroll_bars_hook'. */
7086 static void
7087 XTjudge_scroll_bars (struct frame *f)
7089 Lisp_Object bar, next;
7091 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
7093 /* Clear out the condemned list now so we won't try to process any
7094 more events on the hapless scroll bars. */
7095 fset_condemned_scroll_bars (f, Qnil);
7097 for (; ! NILP (bar); bar = next)
7099 struct scroll_bar *b = XSCROLL_BAR (bar);
7101 x_scroll_bar_remove (b);
7103 next = b->next;
7104 b->next = b->prev = Qnil;
7107 /* Now there should be no references to the condemned scroll bars,
7108 and they should get garbage-collected. */
7112 #ifndef USE_TOOLKIT_SCROLL_BARS
7113 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
7114 is a no-op when using toolkit scroll bars.
7116 This may be called from a signal handler, so we have to ignore GC
7117 mark bits. */
7119 static void
7120 x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
7122 Window w = bar->x_window;
7123 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7124 GC gc = f->output_data.x->normal_gc;
7126 block_input ();
7128 x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
7130 /* Switch to scroll bar foreground color. */
7131 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7132 XSetForeground (FRAME_X_DISPLAY (f), gc,
7133 f->output_data.x->scroll_bar_foreground_pixel);
7135 /* Draw a one-pixel border just inside the edges of the scroll bar. */
7136 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
7137 /* x, y, width, height */
7138 0, 0, bar->width - 1, bar->height - 1);
7140 /* Restore the foreground color of the GC if we changed it above. */
7141 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7142 XSetForeground (FRAME_X_DISPLAY (f), gc,
7143 FRAME_FOREGROUND_PIXEL (f));
7145 unblock_input ();
7148 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7150 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
7151 is set to something other than NO_EVENT, it is enqueued.
7153 This may be called from a signal handler, so we have to ignore GC
7154 mark bits. */
7157 static void
7158 x_scroll_bar_handle_click (struct scroll_bar *bar,
7159 const XEvent *event,
7160 struct input_event *emacs_event)
7162 if (! WINDOWP (bar->window))
7163 emacs_abort ();
7165 emacs_event->kind = (bar->horizontal
7166 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
7167 : SCROLL_BAR_CLICK_EVENT);
7168 emacs_event->code = event->xbutton.button - Button1;
7169 emacs_event->modifiers
7170 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
7171 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
7172 event->xbutton.state)
7173 | (event->type == ButtonRelease
7174 ? up_modifier
7175 : down_modifier));
7176 emacs_event->frame_or_window = bar->window;
7177 emacs_event->arg = Qnil;
7178 emacs_event->timestamp = event->xbutton.time;
7179 if (bar->horizontal)
7181 int left_range
7182 = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
7183 int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
7185 if (x < 0) x = 0;
7186 if (x > left_range) x = left_range;
7188 if (x < bar->start)
7189 emacs_event->part = scroll_bar_before_handle;
7190 else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
7191 emacs_event->part = scroll_bar_horizontal_handle;
7192 else
7193 emacs_event->part = scroll_bar_after_handle;
7195 #ifndef USE_TOOLKIT_SCROLL_BARS
7196 /* If the user has released the handle, set it to its final position. */
7197 if (event->type == ButtonRelease && bar->dragging != -1)
7199 int new_start = - bar->dragging;
7200 int new_end = new_start + bar->end - bar->start;
7202 x_scroll_bar_set_handle (bar, new_start, new_end, false);
7203 bar->dragging = -1;
7205 #endif
7207 XSETINT (emacs_event->x, left_range);
7208 XSETINT (emacs_event->y, x);
7210 else
7212 int top_range
7213 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
7214 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
7216 if (y < 0) y = 0;
7217 if (y > top_range) y = top_range;
7219 if (y < bar->start)
7220 emacs_event->part = scroll_bar_above_handle;
7221 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
7222 emacs_event->part = scroll_bar_handle;
7223 else
7224 emacs_event->part = scroll_bar_below_handle;
7226 #ifndef USE_TOOLKIT_SCROLL_BARS
7227 /* If the user has released the handle, set it to its final position. */
7228 if (event->type == ButtonRelease && bar->dragging != -1)
7230 int new_start = y - bar->dragging;
7231 int new_end = new_start + bar->end - bar->start;
7233 x_scroll_bar_set_handle (bar, new_start, new_end, false);
7234 bar->dragging = -1;
7236 #endif
7238 XSETINT (emacs_event->x, y);
7239 XSETINT (emacs_event->y, top_range);
7243 #ifndef USE_TOOLKIT_SCROLL_BARS
7245 /* Handle some mouse motion while someone is dragging the scroll bar.
7247 This may be called from a signal handler, so we have to ignore GC
7248 mark bits. */
7250 static void
7251 x_scroll_bar_note_movement (struct scroll_bar *bar,
7252 const XMotionEvent *event)
7254 struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
7255 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
7257 dpyinfo->last_mouse_movement_time = event->time;
7258 dpyinfo->last_mouse_scroll_bar = bar;
7259 f->mouse_moved = true;
7261 /* If we're dragging the bar, display it. */
7262 if (bar->dragging != -1)
7264 /* Where should the handle be now? */
7265 int new_start = event->y - bar->dragging;
7267 if (new_start != bar->start)
7269 int new_end = new_start + bar->end - bar->start;
7271 x_scroll_bar_set_handle (bar, new_start, new_end, false);
7276 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7278 /* Return information to the user about the current position of the mouse
7279 on the scroll bar. */
7281 static void
7282 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
7283 enum scroll_bar_part *part, Lisp_Object *x,
7284 Lisp_Object *y, Time *timestamp)
7286 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
7287 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
7288 Window w = bar->x_window;
7289 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7290 int win_x, win_y;
7291 Window dummy_window;
7292 int dummy_coord;
7293 unsigned int dummy_mask;
7295 block_input ();
7297 /* Get the mouse's position relative to the scroll bar window, and
7298 report that. */
7299 if (XQueryPointer (FRAME_X_DISPLAY (f), w,
7301 /* Root, child, root x and root y. */
7302 &dummy_window, &dummy_window,
7303 &dummy_coord, &dummy_coord,
7305 /* Position relative to scroll bar. */
7306 &win_x, &win_y,
7308 /* Mouse buttons and modifier keys. */
7309 &dummy_mask))
7311 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
7313 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
7315 if (bar->dragging != -1)
7316 win_y -= bar->dragging;
7318 if (win_y < 0)
7319 win_y = 0;
7320 if (win_y > top_range)
7321 win_y = top_range;
7323 *fp = f;
7324 *bar_window = bar->window;
7326 if (bar->dragging != -1)
7327 *part = scroll_bar_handle;
7328 else if (win_y < bar->start)
7329 *part = scroll_bar_above_handle;
7330 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
7331 *part = scroll_bar_handle;
7332 else
7333 *part = scroll_bar_below_handle;
7335 XSETINT (*x, win_y);
7336 XSETINT (*y, top_range);
7338 f->mouse_moved = false;
7339 dpyinfo->last_mouse_scroll_bar = NULL;
7340 *timestamp = dpyinfo->last_mouse_movement_time;
7343 unblock_input ();
7347 /* Return information to the user about the current position of the mouse
7348 on the scroll bar. */
7350 static void
7351 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
7352 enum scroll_bar_part *part, Lisp_Object *x,
7353 Lisp_Object *y, Time *timestamp)
7355 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
7356 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
7357 Window w = bar->x_window;
7358 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7359 int win_x, win_y;
7360 Window dummy_window;
7361 int dummy_coord;
7362 unsigned int dummy_mask;
7364 block_input ();
7366 /* Get the mouse's position relative to the scroll bar window, and
7367 report that. */
7368 if (XQueryPointer (FRAME_X_DISPLAY (f), w,
7370 /* Root, child, root x and root y. */
7371 &dummy_window, &dummy_window,
7372 &dummy_coord, &dummy_coord,
7374 /* Position relative to scroll bar. */
7375 &win_x, &win_y,
7377 /* Mouse buttons and modifier keys. */
7378 &dummy_mask))
7380 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
7382 win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
7384 if (bar->dragging != -1)
7385 win_x -= bar->dragging;
7387 if (win_x < 0)
7388 win_x = 0;
7389 if (win_x > left_range)
7390 win_x = left_range;
7392 *fp = f;
7393 *bar_window = bar->window;
7395 if (bar->dragging != -1)
7396 *part = scroll_bar_horizontal_handle;
7397 else if (win_x < bar->start)
7398 *part = scroll_bar_before_handle;
7399 else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
7400 *part = scroll_bar_handle;
7401 else
7402 *part = scroll_bar_after_handle;
7404 XSETINT (*y, win_x);
7405 XSETINT (*x, left_range);
7407 f->mouse_moved = false;
7408 dpyinfo->last_mouse_scroll_bar = NULL;
7409 *timestamp = dpyinfo->last_mouse_movement_time;
7412 unblock_input ();
7416 /* The screen has been cleared so we may have changed foreground or
7417 background colors, and the scroll bars may need to be redrawn.
7418 Clear out the scroll bars, and ask for expose events, so we can
7419 redraw them. */
7421 static void
7422 x_scroll_bar_clear (struct frame *f)
7424 #ifndef USE_TOOLKIT_SCROLL_BARS
7425 Lisp_Object bar;
7427 /* We can have scroll bars even if this is 0,
7428 if we just turned off scroll bar mode.
7429 But in that case we should not clear them. */
7430 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
7431 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7432 bar = XSCROLL_BAR (bar)->next)
7433 XClearArea (FRAME_X_DISPLAY (f),
7434 XSCROLL_BAR (bar)->x_window,
7435 0, 0, 0, 0, True);
7436 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7439 #ifdef ENABLE_CHECKING
7441 /* Record the last 100 characters stored
7442 to help debug the loss-of-chars-during-GC problem. */
7444 static int temp_index;
7445 static short temp_buffer[100];
7447 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
7448 if (temp_index == ARRAYELTS (temp_buffer)) \
7449 temp_index = 0; \
7450 temp_buffer[temp_index++] = (keysym)
7452 #else /* not ENABLE_CHECKING */
7454 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
7456 #endif /* ENABLE_CHECKING */
7458 /* Set this to nonzero to fake an "X I/O error"
7459 on a particular display. */
7461 static struct x_display_info *XTread_socket_fake_io_error;
7463 /* When we find no input here, we occasionally do a no-op command
7464 to verify that the X server is still running and we can still talk with it.
7465 We try all the open displays, one by one.
7466 This variable is used for cycling thru the displays. */
7468 static struct x_display_info *next_noop_dpyinfo;
7470 enum
7472 X_EVENT_NORMAL,
7473 X_EVENT_GOTO_OUT,
7474 X_EVENT_DROP
7477 /* Filter events for the current X input method.
7478 DPYINFO is the display this event is for.
7479 EVENT is the X event to filter.
7481 Returns non-zero if the event was filtered, caller shall not process
7482 this event further.
7483 Returns zero if event is wasn't filtered. */
7485 #ifdef HAVE_X_I18N
7486 static int
7487 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
7489 /* XFilterEvent returns non-zero if the input method has
7490 consumed the event. We pass the frame's X window to
7491 XFilterEvent because that's the one for which the IC
7492 was created. */
7494 struct frame *f1 = x_any_window_to_frame (dpyinfo,
7495 event->xclient.window);
7497 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
7499 #endif
7501 #ifdef USE_GTK
7502 static int current_count;
7503 static int current_finish;
7504 static struct input_event *current_hold_quit;
7506 /* This is the filter function invoked by the GTK event loop.
7507 It is invoked before the XEvent is translated to a GdkEvent,
7508 so we have a chance to act on the event before GTK. */
7509 static GdkFilterReturn
7510 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
7512 XEvent *xev = (XEvent *) gxev;
7514 block_input ();
7515 if (current_count >= 0)
7517 struct x_display_info *dpyinfo;
7519 dpyinfo = x_display_info_for_display (xev->xany.display);
7521 #ifdef HAVE_X_I18N
7522 /* Filter events for the current X input method.
7523 GTK calls XFilterEvent but not for key press and release,
7524 so we do it here. */
7525 if ((xev->type == KeyPress || xev->type == KeyRelease)
7526 && dpyinfo
7527 && x_filter_event (dpyinfo, xev))
7529 unblock_input ();
7530 return GDK_FILTER_REMOVE;
7532 #endif
7534 if (! dpyinfo)
7535 current_finish = X_EVENT_NORMAL;
7536 else
7537 current_count
7538 += handle_one_xevent (dpyinfo, xev, &current_finish,
7539 current_hold_quit);
7541 else
7542 current_finish = x_dispatch_event (xev, xev->xany.display);
7544 unblock_input ();
7546 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
7547 return GDK_FILTER_REMOVE;
7549 return GDK_FILTER_CONTINUE;
7551 #endif /* USE_GTK */
7554 static void xembed_send_message (struct frame *f, Time,
7555 enum xembed_message,
7556 long detail, long data1, long data2);
7558 static void
7559 x_net_wm_state (struct frame *f, Window window)
7561 int value = FULLSCREEN_NONE;
7562 Lisp_Object lval = Qnil;
7563 bool sticky = false;
7565 get_current_wm_state (f, window, &value, &sticky);
7567 switch (value)
7569 case FULLSCREEN_WIDTH:
7570 lval = Qfullwidth;
7571 break;
7572 case FULLSCREEN_HEIGHT:
7573 lval = Qfullheight;
7574 break;
7575 case FULLSCREEN_BOTH:
7576 lval = Qfullboth;
7577 break;
7578 case FULLSCREEN_MAXIMIZED:
7579 lval = Qmaximized;
7580 break;
7583 frame_size_history_add
7584 (f, Qx_net_wm_state, 0, 0,
7585 list2 (get_frame_param (f, Qfullscreen), lval));
7587 store_frame_param (f, Qfullscreen, lval);
7588 /** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
7591 /* Flip back buffers on any frames with undrawn content. */
7592 static void
7593 flush_dirty_back_buffers (void)
7595 block_input ();
7596 Lisp_Object tail, frame;
7597 FOR_EACH_FRAME (tail, frame)
7599 struct frame *f = XFRAME (frame);
7600 if (FRAME_LIVE_P (f) &&
7601 FRAME_X_P (f) &&
7602 FRAME_X_WINDOW (f) &&
7603 !FRAME_GARBAGED_P (f) &&
7604 !buffer_flipping_blocked_p () &&
7605 FRAME_X_NEED_BUFFER_FLIP (f))
7606 show_back_buffer (f);
7608 unblock_input ();
7611 /* Handles the XEvent EVENT on display DPYINFO.
7613 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
7614 *FINISH is zero if caller should continue reading events.
7615 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
7616 *EVENT is unchanged unless we're processing KeyPress event.
7618 We return the number of characters stored into the buffer. */
7620 static int
7621 handle_one_xevent (struct x_display_info *dpyinfo,
7622 const XEvent *event,
7623 int *finish, struct input_event *hold_quit)
7625 union buffered_input_event inev;
7626 int count = 0;
7627 int do_help = 0;
7628 ptrdiff_t nbytes = 0;
7629 struct frame *any, *f = NULL;
7630 struct coding_system coding;
7631 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
7632 /* This holds the state XLookupString needs to implement dead keys
7633 and other tricks known as "compose processing". _X Window System_
7634 says that a portable program can't use this, but Stephen Gildea assures
7635 me that letting the compiler initialize it to zeros will work okay. */
7636 static XComposeStatus compose_status;
7637 XEvent configureEvent;
7638 XEvent next_event;
7640 USE_SAFE_ALLOCA;
7642 *finish = X_EVENT_NORMAL;
7644 EVENT_INIT (inev.ie);
7645 inev.ie.kind = NO_EVENT;
7646 inev.ie.arg = Qnil;
7648 any = x_any_window_to_frame (dpyinfo, event->xany.window);
7650 if (any && any->wait_event_type == event->type)
7651 any->wait_event_type = 0; /* Indicates we got it. */
7653 switch (event->type)
7655 case ClientMessage:
7657 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
7658 && event->xclient.format == 32)
7660 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
7662 /* Use the value returned by x_any_window_to_frame
7663 because this could be the shell widget window
7664 if the frame has no title bar. */
7665 f = any;
7666 #ifdef HAVE_X_I18N
7667 /* Not quite sure this is needed -pd */
7668 if (f && FRAME_XIC (f))
7669 XSetICFocus (FRAME_XIC (f));
7670 #endif
7671 #if false
7672 /* Emacs sets WM hints whose `input' field is `true'. This
7673 instructs the WM to set the input focus automatically for
7674 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
7675 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
7676 it has set the focus. So, XSetInputFocus below is not
7677 needed.
7679 The call to XSetInputFocus below has also caused trouble. In
7680 cases where the XSetInputFocus done by the WM and the one
7681 below are temporally close (on a fast machine), the call
7682 below can generate additional FocusIn events which confuse
7683 Emacs. */
7685 /* Since we set WM_TAKE_FOCUS, we must call
7686 XSetInputFocus explicitly. But not if f is null,
7687 since that might be an event for a deleted frame. */
7688 if (f)
7690 Display *d = event->xclient.display;
7691 /* Catch and ignore errors, in case window has been
7692 iconified by a window manager such as GWM. */
7693 x_catch_errors (d);
7694 XSetInputFocus (d, event->xclient.window,
7695 /* The ICCCM says this is
7696 the only valid choice. */
7697 RevertToParent,
7698 event->xclient.data.l[1]);
7699 x_uncatch_errors ();
7701 /* Not certain about handling scroll bars here */
7702 #endif
7703 goto done;
7706 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
7708 /* Save state modify the WM_COMMAND property to
7709 something which can reinstate us. This notifies
7710 the session manager, who's looking for such a
7711 PropertyNotify. Can restart processing when
7712 a keyboard or mouse event arrives. */
7713 /* If we have a session manager, don't set this.
7714 KDE will then start two Emacsen, one for the
7715 session manager and one for this. */
7716 #ifdef HAVE_X_SM
7717 if (! x_session_have_connection ())
7718 #endif
7720 f = x_top_window_to_frame (dpyinfo,
7721 event->xclient.window);
7722 /* This is just so we only give real data once
7723 for a single Emacs process. */
7724 if (f == SELECTED_FRAME ())
7725 XSetCommand (FRAME_X_DISPLAY (f),
7726 event->xclient.window,
7727 initial_argv, initial_argc);
7728 else if (f)
7729 XSetCommand (FRAME_X_DISPLAY (f),
7730 event->xclient.window,
7731 0, 0);
7733 goto done;
7736 if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
7738 f = any;
7739 if (!f)
7740 goto OTHER; /* May be a dialog that is to be removed */
7742 inev.ie.kind = DELETE_WINDOW_EVENT;
7743 XSETFRAME (inev.ie.frame_or_window, f);
7744 goto done;
7747 goto done;
7750 if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
7751 goto done;
7753 if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
7755 int new_x, new_y;
7756 f = x_window_to_frame (dpyinfo, event->xclient.window);
7758 new_x = event->xclient.data.s[0];
7759 new_y = event->xclient.data.s[1];
7761 if (f)
7763 f->left_pos = new_x;
7764 f->top_pos = new_y;
7766 goto done;
7769 #ifdef X_TOOLKIT_EDITRES
7770 if (event->xclient.message_type == dpyinfo->Xatom_editres)
7772 f = any;
7773 if (f)
7774 _XEditResCheckMessages (f->output_data.x->widget,
7775 NULL, (XEvent *) event, NULL);
7776 goto done;
7778 #endif /* X_TOOLKIT_EDITRES */
7780 if (event->xclient.message_type == dpyinfo->Xatom_DONE
7781 || event->xclient.message_type == dpyinfo->Xatom_PAGE)
7783 /* Ghostview job completed. Kill it. We could
7784 reply with "Next" if we received "Page", but we
7785 currently never do because we are interested in
7786 images, only, which should have 1 page. */
7787 Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
7788 f = x_window_to_frame (dpyinfo, event->xclient.window);
7789 if (!f)
7790 goto OTHER;
7791 x_kill_gs_process (pixmap, f);
7792 expose_frame (f, 0, 0, 0, 0);
7793 goto done;
7796 #ifdef USE_TOOLKIT_SCROLL_BARS
7797 /* Scroll bar callbacks send a ClientMessage from which
7798 we construct an input_event. */
7799 if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
7801 x_scroll_bar_to_input_event (event, &inev.ie);
7802 *finish = X_EVENT_GOTO_OUT;
7803 goto done;
7805 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
7807 x_horizontal_scroll_bar_to_input_event (event, &inev.ie);
7808 *finish = X_EVENT_GOTO_OUT;
7809 goto done;
7811 #endif /* USE_TOOLKIT_SCROLL_BARS */
7813 /* XEmbed messages from the embedder (if any). */
7814 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
7816 enum xembed_message msg = event->xclient.data.l[1];
7817 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
7818 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
7820 *finish = X_EVENT_GOTO_OUT;
7821 goto done;
7824 xft_settings_event (dpyinfo, event);
7826 f = any;
7827 if (!f)
7828 goto OTHER;
7829 if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
7830 *finish = X_EVENT_DROP;
7832 break;
7834 case SelectionNotify:
7835 x_display_set_last_user_time (dpyinfo, event->xselection.time);
7836 #ifdef USE_X_TOOLKIT
7837 if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
7838 goto OTHER;
7839 #endif /* not USE_X_TOOLKIT */
7840 x_handle_selection_notify (&event->xselection);
7841 break;
7843 case SelectionClear: /* Someone has grabbed ownership. */
7844 x_display_set_last_user_time (dpyinfo, event->xselectionclear.time);
7845 #ifdef USE_X_TOOLKIT
7846 if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
7847 goto OTHER;
7848 #endif /* USE_X_TOOLKIT */
7850 const XSelectionClearEvent *eventp = &event->xselectionclear;
7852 inev.sie.kind = SELECTION_CLEAR_EVENT;
7853 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
7854 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
7855 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
7857 break;
7859 case SelectionRequest: /* Someone wants our selection. */
7860 x_display_set_last_user_time (dpyinfo, event->xselectionrequest.time);
7861 #ifdef USE_X_TOOLKIT
7862 if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
7863 goto OTHER;
7864 #endif /* USE_X_TOOLKIT */
7866 const XSelectionRequestEvent *eventp = &event->xselectionrequest;
7868 inev.sie.kind = SELECTION_REQUEST_EVENT;
7869 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
7870 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
7871 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
7872 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
7873 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
7874 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
7876 break;
7878 case PropertyNotify:
7879 x_display_set_last_user_time (dpyinfo, event->xproperty.time);
7880 f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
7881 if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
7883 bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
7884 if (not_hidden && FRAME_ICONIFIED_P (f))
7886 /* Gnome shell does not iconify us when C-z is pressed.
7887 It hides the frame. So if our state says we aren't
7888 hidden anymore, treat it as deiconified. */
7889 SET_FRAME_VISIBLE (f, 1);
7890 SET_FRAME_ICONIFIED (f, false);
7891 f->output_data.x->has_been_visible = true;
7892 inev.ie.kind = DEICONIFY_EVENT;
7893 XSETFRAME (inev.ie.frame_or_window, f);
7895 else if (! not_hidden && ! FRAME_ICONIFIED_P (f))
7897 SET_FRAME_VISIBLE (f, 0);
7898 SET_FRAME_ICONIFIED (f, true);
7899 inev.ie.kind = ICONIFY_EVENT;
7900 XSETFRAME (inev.ie.frame_or_window, f);
7904 x_handle_property_notify (&event->xproperty);
7905 xft_settings_event (dpyinfo, event);
7906 goto OTHER;
7908 case ReparentNotify:
7909 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
7910 if (f)
7912 /* Maybe we shouldn't set this for child frames ?? */
7913 f->output_data.x->parent_desc = event->xreparent.parent;
7914 if (!FRAME_PARENT_FRAME (f))
7915 x_real_positions (f, &f->left_pos, &f->top_pos);
7916 else
7918 Window root;
7919 unsigned int dummy_uint;
7921 block_input ();
7922 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7923 &root, &f->left_pos, &f->top_pos,
7924 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
7925 unblock_input ();
7928 /* Perhaps reparented due to a WM restart. Reset this. */
7929 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
7930 FRAME_DISPLAY_INFO (f)->net_supported_window = 0;
7932 x_set_frame_alpha (f);
7934 goto OTHER;
7936 case Expose:
7937 f = x_window_to_frame (dpyinfo, event->xexpose.window);
7938 if (f)
7940 if (!FRAME_VISIBLE_P (f))
7942 block_input ();
7943 SET_FRAME_VISIBLE (f, 1);
7944 SET_FRAME_ICONIFIED (f, false);
7945 if (FRAME_X_DOUBLE_BUFFERED_P (f))
7946 font_drop_xrender_surfaces (f);
7947 f->output_data.x->has_been_visible = true;
7948 SET_FRAME_GARBAGED (f);
7949 unblock_input ();
7951 else if (FRAME_GARBAGED_P (f))
7953 #ifdef USE_GTK
7954 /* Go around the back buffer and manually clear the
7955 window the first time we show it. This way, we avoid
7956 showing users the sanity-defying horror of whatever
7957 GtkWindow is rendering beneath us. We've garbaged
7958 the frame, so we'll redraw the whole thing on next
7959 redisplay anyway. Yuck. */
7960 x_clear_area1 (
7961 FRAME_X_DISPLAY (f),
7962 FRAME_X_WINDOW (f),
7963 event->xexpose.x, event->xexpose.y,
7964 event->xexpose.width, event->xexpose.height,
7966 x_clear_under_internal_border (f);
7967 #endif
7971 if (!FRAME_GARBAGED_P (f))
7973 #ifdef USE_GTK
7974 /* This seems to be needed for GTK 2.6 and later, see
7975 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
7976 x_clear_area (f,
7977 event->xexpose.x, event->xexpose.y,
7978 event->xexpose.width, event->xexpose.height);
7979 #endif
7980 expose_frame (f, event->xexpose.x, event->xexpose.y,
7981 event->xexpose.width, event->xexpose.height);
7982 #ifdef USE_GTK
7983 x_clear_under_internal_border (f);
7984 #endif
7987 if (!FRAME_GARBAGED_P (f))
7988 show_back_buffer (f);
7990 else
7992 #ifndef USE_TOOLKIT_SCROLL_BARS
7993 struct scroll_bar *bar;
7994 #endif
7995 #if defined USE_LUCID
7996 /* Submenus of the Lucid menu bar aren't widgets
7997 themselves, so there's no way to dispatch events
7998 to them. Recognize this case separately. */
8000 Widget widget = x_window_to_menu_bar (event->xexpose.window);
8001 if (widget)
8002 xlwmenu_redisplay (widget);
8004 #endif /* USE_LUCID */
8006 #ifdef USE_TOOLKIT_SCROLL_BARS
8007 /* Dispatch event to the widget. */
8008 goto OTHER;
8009 #else /* not USE_TOOLKIT_SCROLL_BARS */
8010 bar = x_window_to_scroll_bar (event->xexpose.display,
8011 event->xexpose.window, 2);
8013 if (bar)
8014 x_scroll_bar_expose (bar, event);
8015 #ifdef USE_X_TOOLKIT
8016 else
8017 goto OTHER;
8018 #endif /* USE_X_TOOLKIT */
8019 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8021 break;
8023 case GraphicsExpose: /* This occurs when an XCopyArea's
8024 source area was obscured or not
8025 available. */
8026 f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
8027 if (f)
8029 expose_frame (f, event->xgraphicsexpose.x,
8030 event->xgraphicsexpose.y,
8031 event->xgraphicsexpose.width,
8032 event->xgraphicsexpose.height);
8033 #ifdef USE_GTK
8034 x_clear_under_internal_border (f);
8035 #endif
8036 show_back_buffer (f);
8038 #ifdef USE_X_TOOLKIT
8039 else
8040 goto OTHER;
8041 #endif /* USE_X_TOOLKIT */
8042 break;
8044 case NoExpose: /* This occurs when an XCopyArea's
8045 source area was completely
8046 available. */
8047 break;
8049 case UnmapNotify:
8050 /* Redo the mouse-highlight after the tooltip has gone. */
8051 if (event->xunmap.window == tip_window)
8053 tip_window = 0;
8054 x_redo_mouse_highlight (dpyinfo);
8057 f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
8058 if (f) /* F may no longer exist if
8059 the frame was deleted. */
8061 bool visible = FRAME_VISIBLE_P (f);
8062 /* While a frame is unmapped, display generation is
8063 disabled; you don't want to spend time updating a
8064 display that won't ever be seen. */
8065 SET_FRAME_VISIBLE (f, 0);
8066 /* We can't distinguish, from the event, whether the window
8067 has become iconified or invisible. So assume, if it
8068 was previously visible, than now it is iconified.
8069 But x_make_frame_invisible clears both
8070 the visible flag and the iconified flag;
8071 and that way, we know the window is not iconified now. */
8072 if (visible || FRAME_ICONIFIED_P (f))
8074 SET_FRAME_ICONIFIED (f, true);
8075 inev.ie.kind = ICONIFY_EVENT;
8076 XSETFRAME (inev.ie.frame_or_window, f);
8079 goto OTHER;
8081 case MapNotify:
8082 /* We use x_top_window_to_frame because map events can
8083 come for sub-windows and they don't mean that the
8084 frame is visible. */
8085 f = x_top_window_to_frame (dpyinfo, event->xmap.window);
8086 if (f)
8088 bool iconified = FRAME_ICONIFIED_P (f);
8090 /* Check if fullscreen was specified before we where mapped the
8091 first time, i.e. from the command line. */
8092 if (!f->output_data.x->has_been_visible)
8095 x_check_fullscreen (f);
8096 #ifndef USE_GTK
8097 /* For systems that cannot synthesize `skip_taskbar' for
8098 unmapped windows do the following. */
8099 if (FRAME_SKIP_TASKBAR (f))
8100 x_set_skip_taskbar (f, Qt, Qnil);
8101 #endif /* Not USE_GTK */
8104 if (!iconified)
8106 /* The `z-group' is reset every time a frame becomes
8107 invisible. Handle this here. */
8108 if (FRAME_Z_GROUP (f) == z_group_above)
8109 x_set_z_group (f, Qabove, Qnil);
8110 else if (FRAME_Z_GROUP (f) == z_group_below)
8111 x_set_z_group (f, Qbelow, Qnil);
8114 SET_FRAME_VISIBLE (f, 1);
8115 SET_FRAME_ICONIFIED (f, false);
8116 f->output_data.x->has_been_visible = true;
8118 if (iconified)
8120 inev.ie.kind = DEICONIFY_EVENT;
8121 XSETFRAME (inev.ie.frame_or_window, f);
8123 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
8124 /* Force a redisplay sooner or later to update the
8125 frame titles in case this is the second frame. */
8126 record_asynch_buffer_change ();
8128 goto OTHER;
8130 case KeyPress:
8132 x_display_set_last_user_time (dpyinfo, event->xkey.time);
8133 ignore_next_mouse_click_timeout = 0;
8135 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8136 /* Dispatch KeyPress events when in menu. */
8137 if (popup_activated ())
8138 goto OTHER;
8139 #endif
8141 f = any;
8143 /* If mouse-highlight is an integer, input clears out
8144 mouse highlighting. */
8145 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
8146 #if ! defined (USE_GTK)
8147 && (f == 0
8148 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
8149 #endif
8152 clear_mouse_face (hlinfo);
8153 hlinfo->mouse_face_hidden = true;
8156 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
8157 if (f == 0)
8159 /* Scroll bars consume key events, but we want
8160 the keys to go to the scroll bar's frame. */
8161 Widget widget = XtWindowToWidget (dpyinfo->display,
8162 event->xkey.window);
8163 if (widget && XmIsScrollBar (widget))
8165 widget = XtParent (widget);
8166 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
8169 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
8171 if (f != 0)
8173 KeySym keysym, orig_keysym;
8174 /* al%imercury@uunet.uu.net says that making this 81
8175 instead of 80 fixed a bug whereby meta chars made
8176 his Emacs hang.
8178 It seems that some version of XmbLookupString has
8179 a bug of not returning XBufferOverflow in
8180 status_return even if the input is too long to
8181 fit in 81 bytes. So, we must prepare sufficient
8182 bytes for copy_buffer. 513 bytes (256 chars for
8183 two-byte character set) seems to be a fairly good
8184 approximation. -- 2000.8.10 handa@etl.go.jp */
8185 unsigned char copy_buffer[513];
8186 unsigned char *copy_bufptr = copy_buffer;
8187 int copy_bufsiz = sizeof (copy_buffer);
8188 int modifiers;
8189 Lisp_Object coding_system = Qlatin_1;
8190 Lisp_Object c;
8191 /* Event will be modified. */
8192 XKeyEvent xkey = event->xkey;
8194 #ifdef USE_GTK
8195 /* Don't pass keys to GTK. A Tab will shift focus to the
8196 tool bar in GTK 2.4. Keys will still go to menus and
8197 dialogs because in that case popup_activated is nonzero
8198 (see above). */
8199 *finish = X_EVENT_DROP;
8200 #endif
8202 xkey.state |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f),
8203 extra_keyboard_modifiers);
8204 modifiers = xkey.state;
8206 /* This will have to go some day... */
8208 /* make_lispy_event turns chars into control chars.
8209 Don't do it here because XLookupString is too eager. */
8210 xkey.state &= ~ControlMask;
8211 xkey.state &= ~(dpyinfo->meta_mod_mask
8212 | dpyinfo->super_mod_mask
8213 | dpyinfo->hyper_mod_mask
8214 | dpyinfo->alt_mod_mask);
8216 /* In case Meta is ComposeCharacter,
8217 clear its status. According to Markus Ehrnsperger
8218 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
8219 this enables ComposeCharacter to work whether or
8220 not it is combined with Meta. */
8221 if (modifiers & dpyinfo->meta_mod_mask)
8222 memset (&compose_status, 0, sizeof (compose_status));
8224 #ifdef HAVE_X_I18N
8225 if (FRAME_XIC (f))
8227 Status status_return;
8229 coding_system = Vlocale_coding_system;
8230 nbytes = XmbLookupString (FRAME_XIC (f),
8231 &xkey, (char *) copy_bufptr,
8232 copy_bufsiz, &keysym,
8233 &status_return);
8234 if (status_return == XBufferOverflow)
8236 copy_bufsiz = nbytes + 1;
8237 copy_bufptr = alloca (copy_bufsiz);
8238 nbytes = XmbLookupString (FRAME_XIC (f),
8239 &xkey, (char *) copy_bufptr,
8240 copy_bufsiz, &keysym,
8241 &status_return);
8243 /* Xutf8LookupString is a new but already deprecated interface. -stef */
8244 if (status_return == XLookupNone)
8245 break;
8246 else if (status_return == XLookupChars)
8248 keysym = NoSymbol;
8249 modifiers = 0;
8251 else if (status_return != XLookupKeySym
8252 && status_return != XLookupBoth)
8253 emacs_abort ();
8255 else
8256 nbytes = XLookupString (&xkey, (char *) copy_bufptr,
8257 copy_bufsiz, &keysym,
8258 &compose_status);
8259 #else
8260 nbytes = XLookupString (&xkey, (char *) copy_bufptr,
8261 copy_bufsiz, &keysym,
8262 &compose_status);
8263 #endif
8265 /* If not using XIM/XIC, and a compose sequence is in progress,
8266 we break here. Otherwise, chars_matched is always 0. */
8267 if (compose_status.chars_matched > 0 && nbytes == 0)
8268 break;
8270 memset (&compose_status, 0, sizeof (compose_status));
8271 orig_keysym = keysym;
8273 /* Common for all keysym input events. */
8274 XSETFRAME (inev.ie.frame_or_window, f);
8275 inev.ie.modifiers
8276 = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
8277 inev.ie.timestamp = xkey.time;
8279 /* First deal with keysyms which have defined
8280 translations to characters. */
8281 if (keysym >= 32 && keysym < 128)
8282 /* Avoid explicitly decoding each ASCII character. */
8284 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
8285 inev.ie.code = keysym;
8286 goto done_keysym;
8289 /* Keysyms directly mapped to Unicode characters. */
8290 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
8292 if (keysym < 0x01000080)
8293 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
8294 else
8295 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8296 inev.ie.code = keysym & 0xFFFFFF;
8297 goto done_keysym;
8300 /* Now non-ASCII. */
8301 if (HASH_TABLE_P (Vx_keysym_table)
8302 && (c = Fgethash (make_number (keysym),
8303 Vx_keysym_table,
8304 Qnil),
8305 NATNUMP (c)))
8307 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
8308 ? ASCII_KEYSTROKE_EVENT
8309 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
8310 inev.ie.code = XFASTINT (c);
8311 goto done_keysym;
8314 /* Random non-modifier sorts of keysyms. */
8315 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
8316 || keysym == XK_Delete
8317 #ifdef XK_ISO_Left_Tab
8318 || (keysym >= XK_ISO_Left_Tab
8319 && keysym <= XK_ISO_Enter)
8320 #endif
8321 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
8322 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
8323 #ifdef HPUX
8324 /* This recognizes the "extended function
8325 keys". It seems there's no cleaner way.
8326 Test IsModifierKey to avoid handling
8327 mode_switch incorrectly. */
8328 || (XK_Select <= keysym && keysym < XK_KP_Space)
8329 #endif
8330 #ifdef XK_dead_circumflex
8331 || orig_keysym == XK_dead_circumflex
8332 #endif
8333 #ifdef XK_dead_grave
8334 || orig_keysym == XK_dead_grave
8335 #endif
8336 #ifdef XK_dead_tilde
8337 || orig_keysym == XK_dead_tilde
8338 #endif
8339 #ifdef XK_dead_diaeresis
8340 || orig_keysym == XK_dead_diaeresis
8341 #endif
8342 #ifdef XK_dead_macron
8343 || orig_keysym == XK_dead_macron
8344 #endif
8345 #ifdef XK_dead_degree
8346 || orig_keysym == XK_dead_degree
8347 #endif
8348 #ifdef XK_dead_acute
8349 || orig_keysym == XK_dead_acute
8350 #endif
8351 #ifdef XK_dead_cedilla
8352 || orig_keysym == XK_dead_cedilla
8353 #endif
8354 #ifdef XK_dead_breve
8355 || orig_keysym == XK_dead_breve
8356 #endif
8357 #ifdef XK_dead_ogonek
8358 || orig_keysym == XK_dead_ogonek
8359 #endif
8360 #ifdef XK_dead_caron
8361 || orig_keysym == XK_dead_caron
8362 #endif
8363 #ifdef XK_dead_doubleacute
8364 || orig_keysym == XK_dead_doubleacute
8365 #endif
8366 #ifdef XK_dead_abovedot
8367 || orig_keysym == XK_dead_abovedot
8368 #endif
8369 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
8370 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
8371 /* Any "vendor-specific" key is ok. */
8372 || (orig_keysym & (1 << 28))
8373 || (keysym != NoSymbol && nbytes == 0))
8374 && ! (IsModifierKey (orig_keysym)
8375 /* The symbols from XK_ISO_Lock
8376 to XK_ISO_Last_Group_Lock
8377 don't have real modifiers but
8378 should be treated similarly to
8379 Mode_switch by Emacs. */
8380 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
8381 || (XK_ISO_Lock <= orig_keysym
8382 && orig_keysym <= XK_ISO_Last_Group_Lock)
8383 #endif
8386 STORE_KEYSYM_FOR_DEBUG (keysym);
8387 /* make_lispy_event will convert this to a symbolic
8388 key. */
8389 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
8390 inev.ie.code = keysym;
8391 goto done_keysym;
8394 { /* Raw bytes, not keysym. */
8395 ptrdiff_t i;
8396 int nchars, len;
8398 for (i = 0, nchars = 0; i < nbytes; i++)
8400 if (ASCII_CHAR_P (copy_bufptr[i]))
8401 nchars++;
8402 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
8405 if (nchars < nbytes)
8407 /* Decode the input data. */
8409 /* The input should be decoded with `coding_system'
8410 which depends on which X*LookupString function
8411 we used just above and the locale. */
8412 setup_coding_system (coding_system, &coding);
8413 coding.src_multibyte = false;
8414 coding.dst_multibyte = true;
8415 /* The input is converted to events, thus we can't
8416 handle composition. Anyway, there's no XIM that
8417 gives us composition information. */
8418 coding.common_flags &= ~CODING_ANNOTATION_MASK;
8420 SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
8421 nbytes);
8422 coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
8423 coding.mode |= CODING_MODE_LAST_BLOCK;
8424 decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
8425 nbytes = coding.produced;
8426 nchars = coding.produced_char;
8427 copy_bufptr = coding.destination;
8430 /* Convert the input data to a sequence of
8431 character events. */
8432 for (i = 0; i < nbytes; i += len)
8434 int ch;
8435 if (nchars == nbytes)
8436 ch = copy_bufptr[i], len = 1;
8437 else
8438 ch = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
8439 inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
8440 ? ASCII_KEYSTROKE_EVENT
8441 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
8442 inev.ie.code = ch;
8443 kbd_buffer_store_buffered_event (&inev, hold_quit);
8446 count += nchars;
8448 inev.ie.kind = NO_EVENT; /* Already stored above. */
8450 if (keysym == NoSymbol)
8451 break;
8453 /* FIXME: check side effects and remove this. */
8454 ((XEvent *) event)->xkey = xkey;
8456 done_keysym:
8457 #ifdef HAVE_X_I18N
8458 /* Don't dispatch this event since XtDispatchEvent calls
8459 XFilterEvent, and two calls in a row may freeze the
8460 client. */
8461 break;
8462 #else
8463 goto OTHER;
8464 #endif
8466 case KeyRelease:
8467 x_display_set_last_user_time (dpyinfo, event->xkey.time);
8468 #ifdef HAVE_X_I18N
8469 /* Don't dispatch this event since XtDispatchEvent calls
8470 XFilterEvent, and two calls in a row may freeze the
8471 client. */
8472 break;
8473 #else
8474 goto OTHER;
8475 #endif
8477 case EnterNotify:
8478 x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
8479 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8481 f = any;
8483 if (f && x_mouse_click_focus_ignore_position)
8484 ignore_next_mouse_click_timeout = event->xmotion.time + 200;
8486 /* EnterNotify counts as mouse movement,
8487 so update things that depend on mouse position. */
8488 if (f && !f->output_data.x->hourglass_p)
8489 note_mouse_movement (f, &event->xmotion);
8490 #ifdef USE_GTK
8491 /* We may get an EnterNotify on the buttons in the toolbar. In that
8492 case we moved out of any highlighted area and need to note this. */
8493 if (!f && dpyinfo->last_mouse_glyph_frame)
8494 note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
8495 #endif
8496 goto OTHER;
8498 case FocusIn:
8499 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8500 goto OTHER;
8502 case LeaveNotify:
8503 x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
8504 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8506 f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
8507 if (f)
8509 if (f == hlinfo->mouse_face_mouse_frame)
8511 /* If we move outside the frame, then we're
8512 certainly no longer on any text in the frame. */
8513 clear_mouse_face (hlinfo);
8514 hlinfo->mouse_face_mouse_frame = 0;
8517 /* Generate a nil HELP_EVENT to cancel a help-echo.
8518 Do it only if there's something to cancel.
8519 Otherwise, the startup message is cleared when
8520 the mouse leaves the frame. */
8521 if (any_help_event_p)
8522 do_help = -1;
8524 #ifdef USE_GTK
8525 /* See comment in EnterNotify above */
8526 else if (dpyinfo->last_mouse_glyph_frame)
8527 note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
8528 #endif
8529 goto OTHER;
8531 case FocusOut:
8532 x_detect_focus_change (dpyinfo, any, event, &inev.ie);
8533 goto OTHER;
8535 case MotionNotify:
8537 x_display_set_last_user_time (dpyinfo, event->xmotion.time);
8538 previous_help_echo_string = help_echo_string;
8539 help_echo_string = Qnil;
8541 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
8542 : x_window_to_frame (dpyinfo, event->xmotion.window));
8544 if (hlinfo->mouse_face_hidden)
8546 hlinfo->mouse_face_hidden = false;
8547 clear_mouse_face (hlinfo);
8550 #ifdef USE_GTK
8551 if (f && xg_event_is_for_scrollbar (f, event))
8552 f = 0;
8553 #endif
8554 if (f)
8556 /* Maybe generate a SELECT_WINDOW_EVENT for
8557 `mouse-autoselect-window' but don't let popup menus
8558 interfere with this (Bug#1261). */
8559 if (!NILP (Vmouse_autoselect_window)
8560 && !popup_activated ()
8561 /* Don't switch if we're currently in the minibuffer.
8562 This tries to work around problems where the
8563 minibuffer gets unselected unexpectedly, and where
8564 you then have to move your mouse all the way down to
8565 the minibuffer to select it. */
8566 && !MINI_WINDOW_P (XWINDOW (selected_window))
8567 /* With `focus-follows-mouse' non-nil create an event
8568 also when the target window is on another frame. */
8569 && (f == XFRAME (selected_frame)
8570 || !NILP (focus_follows_mouse)))
8572 static Lisp_Object last_mouse_window;
8573 Lisp_Object window = window_from_coordinates
8574 (f, event->xmotion.x, event->xmotion.y, 0, false);
8576 /* A window will be autoselected only when it is not
8577 selected now and the last mouse movement event was
8578 not in it. The remainder of the code is a bit vague
8579 wrt what a "window" is. For immediate autoselection,
8580 the window is usually the entire window but for GTK
8581 where the scroll bars don't count. For delayed
8582 autoselection the window is usually the window's text
8583 area including the margins. */
8584 if (WINDOWP (window)
8585 && !EQ (window, last_mouse_window)
8586 && !EQ (window, selected_window))
8588 inev.ie.kind = SELECT_WINDOW_EVENT;
8589 inev.ie.frame_or_window = window;
8592 /* Remember the last window where we saw the mouse. */
8593 last_mouse_window = window;
8596 if (!note_mouse_movement (f, &event->xmotion))
8597 help_echo_string = previous_help_echo_string;
8599 else
8601 #ifndef USE_TOOLKIT_SCROLL_BARS
8602 struct scroll_bar *bar
8603 = x_window_to_scroll_bar (event->xmotion.display,
8604 event->xmotion.window, 2);
8606 if (bar)
8607 x_scroll_bar_note_movement (bar, &event->xmotion);
8608 #endif /* USE_TOOLKIT_SCROLL_BARS */
8610 /* If we move outside the frame, then we're
8611 certainly no longer on any text in the frame. */
8612 clear_mouse_face (hlinfo);
8615 /* If the contents of the global variable help_echo_string
8616 has changed, generate a HELP_EVENT. */
8617 if (!NILP (help_echo_string)
8618 || !NILP (previous_help_echo_string))
8619 do_help = 1;
8620 goto OTHER;
8623 case ConfigureNotify:
8624 /* An opaque move can generate a stream of events as the window
8625 is dragged around. If the connection round trip time isn't
8626 really short, they may come faster than we can respond to
8627 them, given the multiple queries we can do to check window
8628 manager state, translate coordinates, etc.
8630 So if this ConfigureNotify is immediately followed by another
8631 for the same window, use the info from the latest update, and
8632 consider the events all handled. */
8633 /* Opaque resize may be trickier; ConfigureNotify events are
8634 mixed with Expose events for multiple windows. */
8635 configureEvent = *event;
8636 while (XPending (dpyinfo->display))
8638 XNextEvent (dpyinfo->display, &next_event);
8639 if (next_event.type != ConfigureNotify
8640 || next_event.xconfigure.window != event->xconfigure.window
8641 /* Skipping events with different sizes can lead to a
8642 mispositioned mode line at initial window creation.
8643 Only drop window motion events for now. */
8644 || next_event.xconfigure.width != event->xconfigure.width
8645 || next_event.xconfigure.height != event->xconfigure.height)
8647 XPutBackEvent (dpyinfo->display, &next_event);
8648 break;
8650 else
8651 configureEvent = next_event;
8654 f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
8655 /* Unfortunately, we need to call font_drop_xrender_surfaces for
8656 _all_ ConfigureNotify events, otherwise we miss some and
8657 flicker. Don't try to optimize these calls by looking only
8658 for size changes: that's not sufficient. We miss some
8659 surface invalidations and flicker. */
8660 block_input ();
8661 if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
8662 font_drop_xrender_surfaces (f);
8663 unblock_input ();
8664 #ifdef USE_CAIRO
8665 if (f) x_cr_destroy_surface (f);
8666 #endif
8667 #ifdef USE_GTK
8668 if (!f
8669 && (f = any)
8670 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
8672 block_input ();
8673 if (FRAME_X_DOUBLE_BUFFERED_P (f))
8674 font_drop_xrender_surfaces (f);
8675 unblock_input ();
8676 xg_frame_resized (f, configureEvent.xconfigure.width,
8677 configureEvent.xconfigure.height);
8678 #ifdef USE_CAIRO
8679 x_cr_destroy_surface (f);
8680 #endif
8681 f = 0;
8683 #endif
8684 if (f)
8686 /* Don't call x_net_wm_state for the scroll bar window.
8687 (Bug#24963, Bug#25887) */
8688 if (configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
8689 x_net_wm_state (f, configureEvent.xconfigure.window);
8691 #ifdef USE_X_TOOLKIT
8692 /* Tip frames are pure X window, set size for them. */
8693 if (! NILP (tip_frame) && XFRAME (tip_frame) == f)
8695 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
8696 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
8698 SET_FRAME_GARBAGED (f);
8700 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
8701 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
8703 #endif
8705 #ifndef USE_X_TOOLKIT
8706 #ifndef USE_GTK
8707 int width =
8708 FRAME_PIXEL_TO_TEXT_WIDTH (f, configureEvent.xconfigure.width);
8709 int height =
8710 FRAME_PIXEL_TO_TEXT_HEIGHT (f, configureEvent.xconfigure.height);
8712 /* In the toolkit version, change_frame_size
8713 is called by the code that handles resizing
8714 of the EmacsFrame widget. */
8716 /* Even if the number of character rows and columns has
8717 not changed, the font size may have changed, so we need
8718 to check the pixel dimensions as well. */
8719 if (width != FRAME_TEXT_WIDTH (f)
8720 || height != FRAME_TEXT_HEIGHT (f)
8721 || configureEvent.xconfigure.width != FRAME_PIXEL_WIDTH (f)
8722 || configureEvent.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
8724 change_frame_size (f, width, height, false, true, false, true);
8725 x_clear_under_internal_border (f);
8726 SET_FRAME_GARBAGED (f);
8727 cancel_mouse_face (f);
8729 #endif /* not USE_GTK */
8730 #endif
8732 #ifdef USE_GTK
8733 /* GTK creates windows but doesn't map them.
8734 Only get real positions when mapped. */
8735 if (FRAME_GTK_OUTER_WIDGET (f)
8736 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
8737 #endif
8739 int old_left = f->left_pos;
8740 int old_top = f->top_pos;
8741 Lisp_Object frame = Qnil;
8743 XSETFRAME (frame, f);
8745 if (!FRAME_PARENT_FRAME (f))
8746 x_real_positions (f, &f->left_pos, &f->top_pos);
8747 else
8749 Window root;
8750 unsigned int dummy_uint;
8752 block_input ();
8753 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8754 &root, &f->left_pos, &f->top_pos,
8755 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
8756 unblock_input ();
8759 if (old_left != f->left_pos || old_top != f->top_pos)
8761 inev.ie.kind = MOVE_FRAME_EVENT;
8762 XSETFRAME (inev.ie.frame_or_window, f);
8767 #ifdef HAVE_X_I18N
8768 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
8769 xic_set_statusarea (f);
8770 #endif
8773 goto OTHER;
8775 case ButtonRelease:
8776 case ButtonPress:
8778 /* If we decide we want to generate an event to be seen
8779 by the rest of Emacs, we put it here. */
8780 bool tool_bar_p = false;
8782 memset (&compose_status, 0, sizeof (compose_status));
8783 dpyinfo->last_mouse_glyph_frame = NULL;
8784 x_display_set_last_user_time (dpyinfo, event->xbutton.time);
8786 if (x_mouse_grabbed (dpyinfo))
8787 f = dpyinfo->last_mouse_frame;
8788 else
8790 f = x_window_to_frame (dpyinfo, event->xbutton.window);
8792 if (f && event->xbutton.type == ButtonPress
8793 && !popup_activated ()
8794 && !x_window_to_scroll_bar (event->xbutton.display,
8795 event->xbutton.window, 2)
8796 && !FRAME_NO_ACCEPT_FOCUS (f))
8798 /* When clicking into a child frame or when clicking
8799 into a parent frame with the child frame selected and
8800 `no-accept-focus' is not set, select the clicked
8801 frame. */
8802 struct frame *hf = dpyinfo->x_highlight_frame;
8804 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
8806 block_input ();
8807 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8808 RevertToParent, CurrentTime);
8809 if (FRAME_PARENT_FRAME (f))
8810 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8811 unblock_input ();
8816 #ifdef USE_GTK
8817 if (f && xg_event_is_for_scrollbar (f, event))
8818 f = 0;
8819 #endif
8820 if (f)
8822 #if ! defined (USE_GTK)
8823 /* Is this in the tool-bar? */
8824 if (WINDOWP (f->tool_bar_window)
8825 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
8827 Lisp_Object window;
8828 int x = event->xbutton.x;
8829 int y = event->xbutton.y;
8831 window = window_from_coordinates (f, x, y, 0, true);
8832 tool_bar_p = EQ (window, f->tool_bar_window);
8834 if (tool_bar_p && event->xbutton.button < 4)
8835 handle_tool_bar_click
8836 (f, x, y, event->xbutton.type == ButtonPress,
8837 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
8839 #endif /* !USE_GTK */
8841 if (!tool_bar_p)
8842 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8843 if (! popup_activated ())
8844 #endif
8846 if (ignore_next_mouse_click_timeout)
8848 if (event->type == ButtonPress
8849 && event->xbutton.time > ignore_next_mouse_click_timeout)
8851 ignore_next_mouse_click_timeout = 0;
8852 construct_mouse_click (&inev.ie, &event->xbutton, f);
8854 if (event->type == ButtonRelease)
8855 ignore_next_mouse_click_timeout = 0;
8857 else
8858 construct_mouse_click (&inev.ie, &event->xbutton, f);
8860 if (FRAME_X_EMBEDDED_P (f))
8861 xembed_send_message (f, event->xbutton.time,
8862 XEMBED_REQUEST_FOCUS, 0, 0, 0);
8864 else
8866 struct scroll_bar *bar
8867 = x_window_to_scroll_bar (event->xbutton.display,
8868 event->xbutton.window, 2);
8870 #ifdef USE_TOOLKIT_SCROLL_BARS
8871 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
8872 scroll bars. */
8873 if (bar && event->xbutton.state & ControlMask)
8875 x_scroll_bar_handle_click (bar, event, &inev.ie);
8876 *finish = X_EVENT_DROP;
8878 #else /* not USE_TOOLKIT_SCROLL_BARS */
8879 if (bar)
8880 x_scroll_bar_handle_click (bar, event, &inev.ie);
8881 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8884 if (event->type == ButtonPress)
8886 dpyinfo->grabbed |= (1 << event->xbutton.button);
8887 dpyinfo->last_mouse_frame = f;
8888 #if ! defined (USE_GTK)
8889 if (f && !tool_bar_p)
8890 f->last_tool_bar_item = -1;
8891 #endif /* not USE_GTK */
8893 else
8894 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
8896 /* Ignore any mouse motion that happened before this event;
8897 any subsequent mouse-movement Emacs events should reflect
8898 only motion after the ButtonPress/Release. */
8899 if (f != 0)
8900 f->mouse_moved = false;
8902 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8903 f = x_menubar_window_to_frame (dpyinfo, event);
8904 /* For a down-event in the menu bar,
8905 don't pass it to Xt right now.
8906 Instead, save it away
8907 and we will pass it to Xt from kbd_buffer_get_event.
8908 That way, we can run some Lisp code first. */
8909 if (! popup_activated ()
8910 #ifdef USE_GTK
8911 /* Gtk+ menus only react to the first three buttons. */
8912 && event->xbutton.button < 3
8913 #endif
8914 && f && event->type == ButtonPress
8915 /* Verify the event is really within the menu bar
8916 and not just sent to it due to grabbing. */
8917 && event->xbutton.x >= 0
8918 && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
8919 && event->xbutton.y >= 0
8920 && event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
8921 && event->xbutton.same_screen)
8923 if (!f->output_data.x->saved_menu_event)
8924 f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
8925 *f->output_data.x->saved_menu_event = *event;
8926 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
8927 XSETFRAME (inev.ie.frame_or_window, f);
8928 *finish = X_EVENT_DROP;
8930 else
8931 goto OTHER;
8932 #endif /* USE_X_TOOLKIT || USE_GTK */
8934 break;
8936 case CirculateNotify:
8937 goto OTHER;
8939 case CirculateRequest:
8940 goto OTHER;
8942 case VisibilityNotify:
8943 goto OTHER;
8945 case MappingNotify:
8946 /* Someone has changed the keyboard mapping - update the
8947 local cache. */
8948 switch (event->xmapping.request)
8950 case MappingModifier:
8951 x_find_modifier_meanings (dpyinfo);
8952 /* This is meant to fall through. */
8953 case MappingKeyboard:
8954 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
8956 goto OTHER;
8958 case DestroyNotify:
8959 xft_settings_event (dpyinfo, event);
8960 break;
8962 default:
8963 OTHER:
8964 #ifdef USE_X_TOOLKIT
8965 block_input ();
8966 if (*finish != X_EVENT_DROP)
8967 XtDispatchEvent ((XEvent *) event);
8968 unblock_input ();
8969 #endif /* USE_X_TOOLKIT */
8970 break;
8973 done:
8974 if (inev.ie.kind != NO_EVENT)
8976 kbd_buffer_store_buffered_event (&inev, hold_quit);
8977 count++;
8980 if (do_help
8981 && !(hold_quit && hold_quit->kind != NO_EVENT))
8983 Lisp_Object frame;
8985 if (f)
8986 XSETFRAME (frame, f);
8987 else
8988 frame = Qnil;
8990 if (do_help > 0)
8992 any_help_event_p = true;
8993 gen_help_event (help_echo_string, frame, help_echo_window,
8994 help_echo_object, help_echo_pos);
8996 else
8998 help_echo_string = Qnil;
8999 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9001 count++;
9004 /* Sometimes event processing draws to the frame outside redisplay.
9005 To ensure that these changes become visible, draw them here. */
9006 flush_dirty_back_buffers ();
9007 SAFE_FREE ();
9008 return count;
9011 /* Handles the XEvent EVENT on display DISPLAY.
9012 This is used for event loops outside the normal event handling,
9013 i.e. looping while a popup menu or a dialog is posted.
9015 Returns the value handle_one_xevent sets in the finish argument. */
9017 x_dispatch_event (XEvent *event, Display *display)
9019 struct x_display_info *dpyinfo;
9020 int finish = X_EVENT_NORMAL;
9022 dpyinfo = x_display_info_for_display (display);
9024 if (dpyinfo)
9025 handle_one_xevent (dpyinfo, event, &finish, 0);
9027 return finish;
9030 /* Read events coming from the X server.
9031 Return as soon as there are no more events to be read.
9033 Return the number of characters stored into the buffer,
9034 thus pretending to be `read' (except the characters we store
9035 in the keyboard buffer can be multibyte, so are not necessarily
9036 C chars). */
9038 static int
9039 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
9041 int count = 0;
9042 bool event_found = false;
9043 struct x_display_info *dpyinfo = terminal->display_info.x;
9045 block_input ();
9047 /* For debugging, this gives a way to fake an I/O error. */
9048 if (dpyinfo == XTread_socket_fake_io_error)
9050 XTread_socket_fake_io_error = 0;
9051 x_io_error_quitter (dpyinfo->display);
9054 #ifndef USE_GTK
9055 while (XPending (dpyinfo->display))
9057 int finish;
9058 XEvent event;
9060 XNextEvent (dpyinfo->display, &event);
9062 #ifdef HAVE_X_I18N
9063 /* Filter events for the current X input method. */
9064 if (x_filter_event (dpyinfo, &event))
9065 continue;
9066 #endif
9067 event_found = true;
9069 count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
9071 if (finish == X_EVENT_GOTO_OUT)
9072 break;
9075 #else /* USE_GTK */
9077 /* For GTK we must use the GTK event loop. But XEvents gets passed
9078 to our filter function above, and then to the big event switch.
9079 We use a bunch of globals to communicate with our filter function,
9080 that is kind of ugly, but it works.
9082 There is no way to do one display at the time, GTK just does events
9083 from all displays. */
9085 while (gtk_events_pending ())
9087 current_count = count;
9088 current_hold_quit = hold_quit;
9090 gtk_main_iteration ();
9092 count = current_count;
9093 current_count = -1;
9094 current_hold_quit = 0;
9096 if (current_finish == X_EVENT_GOTO_OUT)
9097 break;
9099 #endif /* USE_GTK */
9101 /* On some systems, an X bug causes Emacs to get no more events
9102 when the window is destroyed. Detect that. (1994.) */
9103 if (! event_found)
9105 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9106 One XNOOP in 100 loops will make Emacs terminate.
9107 B. Bretthauer, 1994 */
9108 x_noop_count++;
9109 if (x_noop_count >= 100)
9111 x_noop_count=0;
9113 if (next_noop_dpyinfo == 0)
9114 next_noop_dpyinfo = x_display_list;
9116 XNoOp (next_noop_dpyinfo->display);
9118 /* Each time we get here, cycle through the displays now open. */
9119 next_noop_dpyinfo = next_noop_dpyinfo->next;
9123 /* If the focus was just given to an auto-raising frame,
9124 raise it now. FIXME: handle more than one such frame. */
9125 if (dpyinfo->x_pending_autoraise_frame)
9127 x_raise_frame (dpyinfo->x_pending_autoraise_frame);
9128 dpyinfo->x_pending_autoraise_frame = NULL;
9131 unblock_input ();
9133 return count;
9139 /***********************************************************************
9140 Text Cursor
9141 ***********************************************************************/
9143 /* Set clipping for output in glyph row ROW. W is the window in which
9144 we operate. GC is the graphics context to set clipping in.
9146 ROW may be a text row or, e.g., a mode line. Text rows must be
9147 clipped to the interior of the window dedicated to text display,
9148 mode lines must be clipped to the whole window. */
9150 static void
9151 x_clip_to_row (struct window *w, struct glyph_row *row,
9152 enum glyph_row_area area, GC gc)
9154 struct frame *f = XFRAME (WINDOW_FRAME (w));
9155 XRectangle clip_rect;
9156 int window_x, window_y, window_width;
9158 window_box (w, area, &window_x, &window_y, &window_width, 0);
9160 clip_rect.x = window_x;
9161 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
9162 clip_rect.y = max (clip_rect.y, window_y);
9163 clip_rect.width = window_width;
9164 clip_rect.height = row->visible_height;
9166 x_set_clip_rectangles (f, gc, &clip_rect, 1);
9170 /* Draw a hollow box cursor on window W in glyph row ROW. */
9172 static void
9173 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
9175 struct frame *f = XFRAME (WINDOW_FRAME (w));
9176 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
9177 Display *dpy = FRAME_X_DISPLAY (f);
9178 int x, y, wd, h;
9179 XGCValues xgcv;
9180 struct glyph *cursor_glyph;
9181 GC gc;
9183 /* Get the glyph the cursor is on. If we can't tell because
9184 the current matrix is invalid or such, give up. */
9185 cursor_glyph = get_phys_cursor_glyph (w);
9186 if (cursor_glyph == NULL)
9187 return;
9189 /* Compute frame-relative coordinates for phys cursor. */
9190 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
9191 wd = w->phys_cursor_width - 1;
9193 /* The foreground of cursor_gc is typically the same as the normal
9194 background color, which can cause the cursor box to be invisible. */
9195 xgcv.foreground = f->output_data.x->cursor_pixel;
9196 if (dpyinfo->scratch_cursor_gc)
9197 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9198 else
9199 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
9200 GCForeground, &xgcv);
9201 gc = dpyinfo->scratch_cursor_gc;
9203 /* When on R2L character, show cursor at the right edge of the
9204 glyph, unless the cursor box is as wide as the glyph or wider
9205 (the latter happens when x-stretch-cursor is non-nil). */
9206 if ((cursor_glyph->resolved_level & 1) != 0
9207 && cursor_glyph->pixel_width > wd)
9209 x += cursor_glyph->pixel_width - wd;
9210 if (wd > 0)
9211 wd -= 1;
9213 /* Set clipping, draw the rectangle, and reset clipping again. */
9214 x_clip_to_row (w, row, TEXT_AREA, gc);
9215 x_draw_rectangle (f, gc, x, y, wd, h - 1);
9216 x_reset_clip_rectangles (f, gc);
9220 /* Draw a bar cursor on window W in glyph row ROW.
9222 Implementation note: One would like to draw a bar cursor with an
9223 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9224 Unfortunately, I didn't find a font yet that has this property set.
9225 --gerd. */
9227 static void
9228 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
9230 struct frame *f = XFRAME (w->frame);
9231 struct glyph *cursor_glyph;
9233 /* If cursor is out of bounds, don't draw garbage. This can happen
9234 in mini-buffer windows when switching between echo area glyphs
9235 and mini-buffer. */
9236 cursor_glyph = get_phys_cursor_glyph (w);
9237 if (cursor_glyph == NULL)
9238 return;
9240 /* Experimental avoidance of cursor on xwidget. */
9241 if (cursor_glyph->type == XWIDGET_GLYPH)
9242 return;
9244 /* If on an image, draw like a normal cursor. That's usually better
9245 visible than drawing a bar, esp. if the image is large so that
9246 the bar might not be in the window. */
9247 if (cursor_glyph->type == IMAGE_GLYPH)
9249 struct glyph_row *r;
9250 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
9251 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
9253 else
9255 Display *dpy = FRAME_X_DISPLAY (f);
9256 Drawable drawable = FRAME_X_DRAWABLE (f);
9257 GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
9258 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
9259 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
9260 XGCValues xgcv;
9262 /* If the glyph's background equals the color we normally draw
9263 the bars cursor in, the bar cursor in its normal color is
9264 invisible. Use the glyph's foreground color instead in this
9265 case, on the assumption that the glyph's colors are chosen so
9266 that the glyph is legible. */
9267 if (face->background == f->output_data.x->cursor_pixel)
9268 xgcv.background = xgcv.foreground = face->foreground;
9269 else
9270 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
9271 xgcv.graphics_exposures = False;
9273 if (gc)
9274 XChangeGC (dpy, gc, mask, &xgcv);
9275 else
9277 gc = XCreateGC (dpy, drawable, mask, &xgcv);
9278 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9281 x_clip_to_row (w, row, TEXT_AREA, gc);
9283 if (kind == BAR_CURSOR)
9285 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9287 if (width < 0)
9288 width = FRAME_CURSOR_WIDTH (f);
9289 width = min (cursor_glyph->pixel_width, width);
9291 w->phys_cursor_width = width;
9293 /* If the character under cursor is R2L, draw the bar cursor
9294 on the right of its glyph, rather than on the left. */
9295 if ((cursor_glyph->resolved_level & 1) != 0)
9296 x += cursor_glyph->pixel_width - width;
9298 x_fill_rectangle (f, gc, x,
9299 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9300 width, row->height);
9302 else /* HBAR_CURSOR */
9304 int dummy_x, dummy_y, dummy_h;
9305 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9307 if (width < 0)
9308 width = row->height;
9310 width = min (row->height, width);
9312 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
9313 &dummy_y, &dummy_h);
9315 if ((cursor_glyph->resolved_level & 1) != 0
9316 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
9317 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
9318 x_fill_rectangle (f, gc, x,
9319 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
9320 row->height - width),
9321 w->phys_cursor_width - 1, width);
9324 x_reset_clip_rectangles (f, gc);
9329 /* RIF: Define cursor CURSOR on frame F. */
9331 static void
9332 x_define_frame_cursor (struct frame *f, Cursor cursor)
9334 if (!f->pointer_invisible
9335 && f->output_data.x->current_cursor != cursor)
9336 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
9337 f->output_data.x->current_cursor = cursor;
9341 /* RIF: Clear area on frame F. */
9343 static void
9344 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
9346 x_clear_area (f, x, y, width, height);
9350 /* RIF: Draw cursor on window W. */
9352 static void
9353 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
9354 int y, enum text_cursor_kinds cursor_type,
9355 int cursor_width, bool on_p, bool active_p)
9357 struct frame *f = XFRAME (WINDOW_FRAME (w));
9359 if (on_p)
9361 w->phys_cursor_type = cursor_type;
9362 w->phys_cursor_on_p = true;
9364 if (glyph_row->exact_window_width_line_p
9365 && (glyph_row->reversed_p
9366 ? (w->phys_cursor.hpos < 0)
9367 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
9369 glyph_row->cursor_in_fringe_p = true;
9370 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
9372 else
9374 switch (cursor_type)
9376 case HOLLOW_BOX_CURSOR:
9377 x_draw_hollow_cursor (w, glyph_row);
9378 break;
9380 case FILLED_BOX_CURSOR:
9381 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9382 break;
9384 case BAR_CURSOR:
9385 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
9386 break;
9388 case HBAR_CURSOR:
9389 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
9390 break;
9392 case NO_CURSOR:
9393 w->phys_cursor_width = 0;
9394 break;
9396 default:
9397 emacs_abort ();
9401 #ifdef HAVE_X_I18N
9402 if (w == XWINDOW (f->selected_window))
9403 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
9404 xic_set_preeditarea (w, x, y);
9405 #endif
9408 XFlush (FRAME_X_DISPLAY (f));
9412 /* Icons. */
9414 /* Make the x-window of frame F use the gnu icon bitmap. */
9416 bool
9417 x_bitmap_icon (struct frame *f, Lisp_Object file)
9419 ptrdiff_t bitmap_id;
9421 if (FRAME_X_WINDOW (f) == 0)
9422 return true;
9424 /* Free up our existing icon bitmap and mask if any. */
9425 if (f->output_data.x->icon_bitmap > 0)
9426 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
9427 f->output_data.x->icon_bitmap = 0;
9429 if (STRINGP (file))
9431 #ifdef USE_GTK
9432 /* Use gtk_window_set_icon_from_file () if available,
9433 It's not restricted to bitmaps */
9434 if (xg_set_icon (f, file))
9435 return false;
9436 #endif /* USE_GTK */
9437 bitmap_id = x_create_bitmap_from_file (f, file);
9438 x_create_bitmap_mask (f, bitmap_id);
9440 else
9442 /* Create the GNU bitmap and mask if necessary. */
9443 if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
9445 ptrdiff_t rc = -1;
9447 #ifdef USE_GTK
9449 if (xg_set_icon (f, xg_default_icon_file)
9450 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
9452 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
9453 return false;
9456 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
9458 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
9459 if (rc != -1)
9460 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
9462 #endif
9464 /* If all else fails, use the (black and white) xbm image. */
9465 if (rc == -1)
9467 rc = x_create_bitmap_from_data (f, (char *) gnu_xbm_bits,
9468 gnu_xbm_width, gnu_xbm_height);
9469 if (rc == -1)
9470 return true;
9472 FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
9473 x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
9477 /* The first time we create the GNU bitmap and mask,
9478 this increments the ref-count one extra time.
9479 As a result, the GNU bitmap and mask are never freed.
9480 That way, we don't have to worry about allocating it again. */
9481 x_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
9483 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
9486 x_wm_set_icon_pixmap (f, bitmap_id);
9487 f->output_data.x->icon_bitmap = bitmap_id;
9489 return false;
9493 /* Make the x-window of frame F use a rectangle with text.
9494 Use ICON_NAME as the text. */
9496 bool
9497 x_text_icon (struct frame *f, const char *icon_name)
9499 if (FRAME_X_WINDOW (f) == 0)
9500 return true;
9503 XTextProperty text;
9504 text.value = (unsigned char *) icon_name;
9505 text.encoding = XA_STRING;
9506 text.format = 8;
9507 text.nitems = strlen (icon_name);
9508 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
9511 if (f->output_data.x->icon_bitmap > 0)
9512 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
9513 f->output_data.x->icon_bitmap = 0;
9514 x_wm_set_icon_pixmap (f, 0);
9516 return false;
9519 #define X_ERROR_MESSAGE_SIZE 200
9521 /* If non-nil, this should be a string.
9522 It means catch X errors and store the error message in this string.
9524 The reason we use a stack is that x_catch_error/x_uncatch_error can
9525 be called from a signal handler.
9528 struct x_error_message_stack {
9529 char string[X_ERROR_MESSAGE_SIZE];
9530 Display *dpy;
9531 x_special_error_handler handler;
9532 void *handler_data;
9533 struct x_error_message_stack *prev;
9535 static struct x_error_message_stack *x_error_message;
9537 /* An X error handler which stores the error message in
9538 *x_error_message. This is called from x_error_handler if
9539 x_catch_errors is in effect. */
9541 static void
9542 x_error_catcher (Display *display, XErrorEvent *event)
9544 XGetErrorText (display, event->error_code,
9545 x_error_message->string,
9546 X_ERROR_MESSAGE_SIZE);
9547 if (x_error_message->handler)
9548 x_error_message->handler (display, event, x_error_message->string,
9549 x_error_message->handler_data);
9552 /* Begin trapping X errors for display DPY. Actually we trap X errors
9553 for all displays, but DPY should be the display you are actually
9554 operating on.
9556 After calling this function, X protocol errors no longer cause
9557 Emacs to exit; instead, they are recorded in the string
9558 stored in *x_error_message.
9560 Calling x_check_errors signals an Emacs error if an X error has
9561 occurred since the last call to x_catch_errors or x_check_errors.
9563 Calling x_uncatch_errors resumes the normal error handling.
9564 Calling x_uncatch_errors_after_check is similar, but skips an XSync
9565 to the server, and should be used only immediately after
9566 x_had_errors_p or x_check_errors. */
9568 void
9569 x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
9570 void *handler_data)
9572 struct x_error_message_stack *data = xmalloc (sizeof *data);
9574 /* Make sure any errors from previous requests have been dealt with. */
9575 XSync (dpy, False);
9577 data->dpy = dpy;
9578 data->string[0] = 0;
9579 data->handler = handler;
9580 data->handler_data = handler_data;
9581 data->prev = x_error_message;
9582 x_error_message = data;
9585 void
9586 x_catch_errors (Display *dpy)
9588 x_catch_errors_with_handler (dpy, NULL, NULL);
9591 /* Undo the last x_catch_errors call.
9592 DPY should be the display that was passed to x_catch_errors.
9594 This version should be used only if the immediately preceding
9595 X-protocol-related thing was x_check_errors or x_had_error_p, both
9596 of which issue XSync calls, so we don't need to re-sync here. */
9598 void
9599 x_uncatch_errors_after_check (void)
9601 struct x_error_message_stack *tmp;
9603 block_input ();
9604 tmp = x_error_message;
9605 x_error_message = x_error_message->prev;
9606 xfree (tmp);
9607 unblock_input ();
9610 /* Undo the last x_catch_errors call.
9611 DPY should be the display that was passed to x_catch_errors. */
9613 void
9614 x_uncatch_errors (void)
9616 struct x_error_message_stack *tmp;
9618 block_input ();
9620 /* The display may have been closed before this function is called.
9621 Check if it is still open before calling XSync. */
9622 if (x_display_info_for_display (x_error_message->dpy) != 0)
9623 XSync (x_error_message->dpy, False);
9625 tmp = x_error_message;
9626 x_error_message = x_error_message->prev;
9627 xfree (tmp);
9628 unblock_input ();
9631 /* If any X protocol errors have arrived since the last call to
9632 x_catch_errors or x_check_errors, signal an Emacs error using
9633 sprintf (a buffer, FORMAT, the x error message text) as the text. */
9635 void
9636 x_check_errors (Display *dpy, const char *format)
9638 /* Make sure to catch any errors incurred so far. */
9639 XSync (dpy, False);
9641 if (x_error_message->string[0])
9643 char string[X_ERROR_MESSAGE_SIZE];
9644 memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE);
9645 x_uncatch_errors ();
9646 error (format, string);
9650 /* Nonzero if we had any X protocol errors
9651 since we did x_catch_errors on DPY. */
9653 bool
9654 x_had_errors_p (Display *dpy)
9656 /* Make sure to catch any errors incurred so far. */
9657 XSync (dpy, False);
9659 return x_error_message->string[0] != 0;
9662 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
9664 void
9665 x_clear_errors (Display *dpy)
9667 x_error_message->string[0] = 0;
9670 #if false
9671 /* See comment in unwind_to_catch why calling this is a bad
9672 * idea. --lorentey */
9673 /* Close off all unclosed x_catch_errors calls. */
9675 void
9676 x_fully_uncatch_errors (void)
9678 while (x_error_message)
9679 x_uncatch_errors ();
9681 #endif
9683 #if false
9684 static unsigned int x_wire_count;
9685 x_trace_wire (void)
9687 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
9689 #endif
9692 /************************************************************************
9693 Handling X errors
9694 ************************************************************************/
9696 /* Error message passed to x_connection_closed. */
9698 static char *error_msg;
9700 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
9701 the text of an error message that lead to the connection loss. */
9703 static _Noreturn void
9704 x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
9706 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
9707 Lisp_Object frame, tail;
9708 ptrdiff_t idx = SPECPDL_INDEX ();
9710 error_msg = alloca (strlen (error_message) + 1);
9711 strcpy (error_msg, error_message);
9713 /* Inhibit redisplay while frames are being deleted. */
9714 specbind (Qinhibit_redisplay, Qt);
9716 if (dpyinfo)
9718 /* Protect display from being closed when we delete the last
9719 frame on it. */
9720 dpyinfo->reference_count++;
9721 dpyinfo->terminal->reference_count++;
9723 if (ioerror) dpyinfo->display = 0;
9725 /* First delete frames whose mini-buffers are on frames
9726 that are on the dead display. */
9727 FOR_EACH_FRAME (tail, frame)
9729 Lisp_Object minibuf_frame;
9730 minibuf_frame
9731 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
9732 if (FRAME_X_P (XFRAME (frame))
9733 && FRAME_X_P (XFRAME (minibuf_frame))
9734 && ! EQ (frame, minibuf_frame)
9735 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
9736 delete_frame (frame, Qnoelisp);
9739 /* Now delete all remaining frames on the dead display.
9740 We are now sure none of these is used as the mini-buffer
9741 for another frame that we need to delete. */
9742 FOR_EACH_FRAME (tail, frame)
9743 if (FRAME_X_P (XFRAME (frame))
9744 && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
9746 /* Set this to t so that delete_frame won't get confused
9747 trying to find a replacement. */
9748 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
9749 delete_frame (frame, Qnoelisp);
9752 /* If DPYINFO is null, this means we didn't open the display in the
9753 first place, so don't try to close it. */
9754 if (dpyinfo)
9756 /* We can not call XtCloseDisplay here because it calls XSync.
9757 XSync inside the error handler apparently hangs Emacs. On
9758 current Xt versions, this isn't needed either. */
9759 #ifdef USE_GTK
9760 /* A long-standing GTK bug prevents proper disconnect handling
9761 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
9762 the resulting Glib error message loop filled a user's disk.
9763 To avoid this, kill Emacs unconditionally on disconnect. */
9764 shut_down_emacs (0, Qnil);
9765 fprintf (stderr, "%s\n\
9766 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
9767 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
9768 For details, see etc/PROBLEMS.\n",
9769 error_msg);
9770 emacs_abort ();
9771 #endif /* USE_GTK */
9773 /* Indicate that this display is dead. */
9774 dpyinfo->display = 0;
9776 dpyinfo->reference_count--;
9777 dpyinfo->terminal->reference_count--;
9778 if (dpyinfo->reference_count != 0)
9779 /* We have just closed all frames on this display. */
9780 emacs_abort ();
9783 Lisp_Object tmp;
9784 XSETTERMINAL (tmp, dpyinfo->terminal);
9785 Fdelete_terminal (tmp, Qnoelisp);
9789 if (terminal_list == 0)
9791 fprintf (stderr, "%s\n", error_msg);
9792 Fkill_emacs (make_number (70));
9793 /* NOTREACHED */
9796 totally_unblock_input ();
9798 unbind_to (idx, Qnil);
9799 clear_waiting_for_input ();
9801 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
9802 longjmp), because returning from this function would get us back into
9803 Xlib's code which will directly call `exit'. */
9804 error ("%s", error_msg);
9807 /* We specifically use it before defining it, so that gcc doesn't inline it,
9808 otherwise gdb doesn't know how to properly put a breakpoint on it. */
9809 static void x_error_quitter (Display *, XErrorEvent *);
9811 /* This is the first-level handler for X protocol errors.
9812 It calls x_error_quitter or x_error_catcher. */
9814 static int
9815 x_error_handler (Display *display, XErrorEvent *event)
9817 #if defined USE_GTK && defined HAVE_GTK3
9818 if ((event->error_code == BadMatch || event->error_code == BadWindow)
9819 && event->request_code == X_SetInputFocus)
9821 return 0;
9823 #endif
9825 if (x_error_message)
9826 x_error_catcher (display, event);
9827 else
9828 x_error_quitter (display, event);
9829 return 0;
9832 /* This is the usual handler for X protocol errors.
9833 It kills all frames on the display that we got the error for.
9834 If that was the only one, it prints an error message and kills Emacs. */
9836 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
9838 /* On older GCC versions, just putting x_error_quitter
9839 after x_error_handler prevents inlining into the former. */
9841 static void NO_INLINE
9842 x_error_quitter (Display *display, XErrorEvent *event)
9844 char buf[256], buf1[356];
9846 /* Ignore BadName errors. They can happen because of fonts
9847 or colors that are not defined. */
9849 if (event->error_code == BadName)
9850 return;
9852 /* Note that there is no real way portable across R3/R4 to get the
9853 original error handler. */
9855 XGetErrorText (display, event->error_code, buf, sizeof (buf));
9856 sprintf (buf1, "X protocol error: %s on protocol request %d",
9857 buf, event->request_code);
9858 x_connection_closed (display, buf1, false);
9862 /* This is the handler for X IO errors, always.
9863 It kills all frames on the display that we lost touch with.
9864 If that was the only one, it prints an error message and kills Emacs. */
9866 static _Noreturn int
9867 x_io_error_quitter (Display *display)
9869 char buf[256];
9871 snprintf (buf, sizeof buf, "Connection lost to X server '%s'",
9872 DisplayString (display));
9873 x_connection_closed (display, buf, true);
9874 assume (false);
9877 /* Changing the font of the frame. */
9879 /* Give frame F the font FONT-OBJECT as its default font. The return
9880 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
9881 frame. If it is negative, generate a new fontset from
9882 FONT-OBJECT. */
9884 Lisp_Object
9885 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
9887 struct font *font = XFONT_OBJECT (font_object);
9888 int unit, font_ascent, font_descent;
9889 #ifndef USE_X_TOOLKIT
9890 int old_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
9891 Lisp_Object fullscreen;
9892 #endif
9894 if (fontset < 0)
9895 fontset = fontset_from_font (font_object);
9896 FRAME_FONTSET (f) = fontset;
9897 if (FRAME_FONT (f) == font)
9898 /* This font is already set in frame F. There's nothing more to
9899 do. */
9900 return font_object;
9902 FRAME_FONT (f) = font;
9903 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
9904 FRAME_COLUMN_WIDTH (f) = font->average_width;
9905 get_font_ascent_descent (font, &font_ascent, &font_descent);
9906 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
9908 #ifndef USE_X_TOOLKIT
9909 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
9910 #endif
9912 /* Compute character columns occupied by scrollbar.
9914 Don't do things differently for non-toolkit scrollbars
9915 (Bug#17163). */
9916 unit = FRAME_COLUMN_WIDTH (f);
9917 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
9918 FRAME_CONFIG_SCROLL_BAR_COLS (f)
9919 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
9920 else
9921 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
9923 if (FRAME_X_WINDOW (f) != 0)
9925 /* Don't change the size of a tip frame; there's no point in
9926 doing it because it's done in Fx_show_tip, and it leads to
9927 problems because the tip frame has no widget. */
9928 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9930 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
9931 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
9932 false, Qfont);
9933 #ifndef USE_X_TOOLKIT
9934 if (FRAME_MENU_BAR_HEIGHT (f) != old_menu_bar_height
9935 && !f->after_make_frame
9936 && (EQ (frame_inhibit_implied_resize, Qt)
9937 || (CONSP (frame_inhibit_implied_resize)
9938 && NILP (Fmemq (Qfont, frame_inhibit_implied_resize))))
9939 && (NILP (fullscreen = get_frame_param (f, Qfullscreen))
9940 || EQ (fullscreen, Qfullwidth)))
9941 /* If the menu bar height changes, try to keep text height
9942 constant. */
9943 adjust_frame_size
9944 (f, -1, FRAME_TEXT_HEIGHT (f) + FRAME_MENU_BAR_HEIGHT (f)
9945 - old_menu_bar_height, 1, false, Qfont);
9946 #endif /* USE_X_TOOLKIT */
9950 #ifdef HAVE_X_I18N
9951 if (FRAME_XIC (f)
9952 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
9954 block_input ();
9955 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
9956 unblock_input ();
9958 #endif
9960 return font_object;
9964 /***********************************************************************
9965 X Input Methods
9966 ***********************************************************************/
9968 #ifdef HAVE_X_I18N
9970 #ifdef HAVE_X11R6
9972 /* XIM destroy callback function, which is called whenever the
9973 connection to input method XIM dies. CLIENT_DATA contains a
9974 pointer to the x_display_info structure corresponding to XIM. */
9976 static void
9977 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
9979 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
9980 Lisp_Object frame, tail;
9982 block_input ();
9984 /* No need to call XDestroyIC.. */
9985 FOR_EACH_FRAME (tail, frame)
9987 struct frame *f = XFRAME (frame);
9988 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
9990 FRAME_XIC (f) = NULL;
9991 xic_free_xfontset (f);
9995 /* No need to call XCloseIM. */
9996 dpyinfo->xim = NULL;
9997 XFree (dpyinfo->xim_styles);
9998 unblock_input ();
10001 #endif /* HAVE_X11R6 */
10003 /* Open the connection to the XIM server on display DPYINFO.
10004 RESOURCE_NAME is the resource name Emacs uses. */
10006 static void
10007 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
10009 XIM xim;
10011 #ifdef HAVE_XIM
10012 if (use_xim)
10014 if (dpyinfo->xim)
10015 XCloseIM (dpyinfo->xim);
10016 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
10017 emacs_class);
10018 dpyinfo->xim = xim;
10020 if (xim)
10022 #ifdef HAVE_X11R6
10023 XIMCallback destroy;
10024 #endif
10026 /* Get supported styles and XIM values. */
10027 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
10029 #ifdef HAVE_X11R6
10030 destroy.callback = xim_destroy_callback;
10031 destroy.client_data = (XPointer)dpyinfo;
10032 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
10033 #endif
10037 else
10038 #endif /* HAVE_XIM */
10039 dpyinfo->xim = NULL;
10043 #ifdef HAVE_X11R6_XIM
10045 /* XIM instantiate callback function, which is called whenever an XIM
10046 server is available. DISPLAY is the display of the XIM.
10047 CLIENT_DATA contains a pointer to an xim_inst_t structure created
10048 when the callback was registered. */
10050 static void
10051 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
10053 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
10054 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
10056 /* We don't support multiple XIM connections. */
10057 if (dpyinfo->xim)
10058 return;
10060 xim_open_dpy (dpyinfo, xim_inst->resource_name);
10062 /* Create XIC for the existing frames on the same display, as long
10063 as they have no XIC. */
10064 if (dpyinfo->xim && dpyinfo->reference_count > 0)
10066 Lisp_Object tail, frame;
10068 block_input ();
10069 FOR_EACH_FRAME (tail, frame)
10071 struct frame *f = XFRAME (frame);
10073 if (FRAME_X_P (f)
10074 && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
10075 if (FRAME_XIC (f) == NULL)
10077 create_frame_xic (f);
10078 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
10079 xic_set_statusarea (f);
10080 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
10082 struct window *w = XWINDOW (f->selected_window);
10083 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
10088 unblock_input ();
10092 #endif /* HAVE_X11R6_XIM */
10095 /* Open a connection to the XIM server on display DPYINFO.
10096 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
10097 connection only at the first time. On X11R6, open the connection
10098 in the XIM instantiate callback function. */
10100 static void
10101 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
10103 dpyinfo->xim = NULL;
10104 #ifdef HAVE_XIM
10105 if (use_xim)
10107 #ifdef HAVE_X11R6_XIM
10108 struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
10109 Bool ret;
10111 dpyinfo->xim_callback_data = xim_inst;
10112 xim_inst->dpyinfo = dpyinfo;
10113 xim_inst->resource_name = xstrdup (resource_name);
10114 ret = XRegisterIMInstantiateCallback
10115 (dpyinfo->display, dpyinfo->xrdb, xim_inst->resource_name,
10116 emacs_class, xim_instantiate_callback,
10117 /* This is XPointer in XFree86 but (XPointer *)
10118 on Tru64, at least, hence the configure test. */
10119 (XRegisterIMInstantiateCallback_arg6) xim_inst);
10120 eassert (ret == True);
10121 #else /* not HAVE_X11R6_XIM */
10122 xim_open_dpy (dpyinfo, resource_name);
10123 #endif /* not HAVE_X11R6_XIM */
10125 #endif /* HAVE_XIM */
10129 /* Close the connection to the XIM server on display DPYINFO. */
10131 static void
10132 xim_close_dpy (struct x_display_info *dpyinfo)
10134 #ifdef HAVE_XIM
10135 if (use_xim)
10137 #ifdef HAVE_X11R6_XIM
10138 struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data;
10140 if (dpyinfo->display)
10142 Bool ret = XUnregisterIMInstantiateCallback
10143 (dpyinfo->display, dpyinfo->xrdb, xim_inst->resource_name,
10144 emacs_class, xim_instantiate_callback,
10145 (XRegisterIMInstantiateCallback_arg6) xim_inst);
10146 eassert (ret == True);
10148 xfree (xim_inst->resource_name);
10149 xfree (xim_inst);
10150 #endif /* HAVE_X11R6_XIM */
10151 if (dpyinfo->display)
10152 XCloseIM (dpyinfo->xim);
10153 dpyinfo->xim = NULL;
10154 XFree (dpyinfo->xim_styles);
10156 #endif /* HAVE_XIM */
10159 #endif /* not HAVE_X11R6_XIM */
10163 /* Calculate the absolute position in frame F
10164 from its current recorded position values and gravity. */
10166 static void
10167 x_calc_absolute_position (struct frame *f)
10169 int flags = f->size_hint_flags;
10170 struct frame *p = FRAME_PARENT_FRAME (f);
10172 /* We have nothing to do if the current position
10173 is already for the top-left corner. */
10174 if (! ((flags & XNegative) || (flags & YNegative)))
10175 return;
10177 /* Treat negative positions as relative to the leftmost bottommost
10178 position that fits on the screen. */
10179 if ((flags & XNegative) && (f->left_pos <= 0))
10181 int width = FRAME_PIXEL_WIDTH (f);
10183 /* A frame that has been visible at least once should have outer
10184 edges. */
10185 if (f->output_data.x->has_been_visible && !p)
10187 Lisp_Object frame;
10188 Lisp_Object edges = Qnil;
10190 XSETFRAME (frame, f);
10191 edges = Fx_frame_edges (frame, Qouter_edges);
10192 if (!NILP (edges))
10193 width = (XINT (Fnth (make_number (2), edges))
10194 - XINT (Fnth (make_number (0), edges)));
10197 if (p)
10198 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
10199 + f->left_pos);
10200 else
10201 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
10202 - width + f->left_pos);
10206 if ((flags & YNegative) && (f->top_pos <= 0))
10208 int height = FRAME_PIXEL_HEIGHT (f);
10210 #if defined USE_X_TOOLKIT && defined USE_MOTIF
10211 /* Something is fishy here. When using Motif, starting Emacs with
10212 `-g -0-0', the frame appears too low by a few pixels.
10214 This seems to be so because initially, while Emacs is starting,
10215 the column widget's height and the frame's pixel height are
10216 different. The column widget's height is the right one. In
10217 later invocations, when Emacs is up, the frame's pixel height
10218 is right, though.
10220 It's not obvious where the initial small difference comes from.
10221 2000-12-01, gerd. */
10223 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
10224 #endif
10226 if (f->output_data.x->has_been_visible && !p)
10228 Lisp_Object frame;
10229 Lisp_Object edges = Qnil;
10231 XSETFRAME (frame, f);
10232 if (NILP (edges))
10233 edges = Fx_frame_edges (frame, Qouter_edges);
10234 if (!NILP (edges))
10235 height = (XINT (Fnth (make_number (3), edges))
10236 - XINT (Fnth (make_number (1), edges)));
10239 if (p)
10240 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
10241 + f->top_pos);
10242 else
10243 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
10244 - height + f->top_pos);
10247 /* The left_pos and top_pos
10248 are now relative to the top and left screen edges,
10249 so the flags should correspond. */
10250 f->size_hint_flags &= ~ (XNegative | YNegative);
10253 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10254 to really change the position, and 0 when calling from
10255 x_make_frame_visible (in that case, XOFF and YOFF are the current
10256 position values). It is -1 when calling from x_set_frame_parameters,
10257 which means, do adjust for borders but don't change the gravity. */
10259 void
10260 x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
10262 int modified_top, modified_left;
10264 if (change_gravity > 0)
10266 f->top_pos = yoff;
10267 f->left_pos = xoff;
10268 f->size_hint_flags &= ~ (XNegative | YNegative);
10269 if (xoff < 0)
10270 f->size_hint_flags |= XNegative;
10271 if (yoff < 0)
10272 f->size_hint_flags |= YNegative;
10273 f->win_gravity = NorthWestGravity;
10276 x_calc_absolute_position (f);
10278 block_input ();
10279 x_wm_set_size_hint (f, 0, false);
10281 #ifdef USE_GTK
10282 if (x_gtk_use_window_move)
10284 /* When a position change was requested and the outer GTK widget
10285 has been realized already, leave it to gtk_window_move to DTRT
10286 and return. Used for Bug#25851 and Bug#25943. */
10287 if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f))
10288 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
10289 f->left_pos, f->top_pos);
10290 unblock_input ();
10291 return;
10293 #endif /* USE_GTK */
10295 modified_left = f->left_pos;
10296 modified_top = f->top_pos;
10298 if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
10300 /* Some WMs (twm, wmaker at least) has an offset that is smaller
10301 than the WM decorations. So we use the calculated offset instead
10302 of the WM decoration sizes here (x/y_pixels_outer_diff). */
10303 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
10304 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
10307 #ifdef USE_GTK
10308 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
10309 modified_left, modified_top);
10310 #else
10311 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10312 modified_left, modified_top);
10313 #endif
10315 x_sync_with_move (f, f->left_pos, f->top_pos,
10316 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
10318 /* change_gravity is non-zero when this function is called from Lisp to
10319 programmatically move a frame. In that case, we call
10320 x_check_expected_move to discover if we have a "Type A" or "Type B"
10321 window manager, and, for a "Type A" window manager, adjust the position
10322 of the frame.
10324 We call x_check_expected_move if a programmatic move occurred, and
10325 either the window manager type (A/B) is unknown or it is Type A but we
10326 need to compute the top/left offset adjustment for this frame. */
10328 if (change_gravity != 0
10329 && !FRAME_PARENT_FRAME (f)
10330 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
10331 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
10332 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
10333 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
10334 x_check_expected_move (f, modified_left, modified_top);
10336 unblock_input ();
10339 /* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
10340 on the root window for frame F contains ATOMNAME.
10341 This is how a WM check shall be done according to the Window Manager
10342 Specification/Extended Window Manager Hints at
10343 http://freedesktop.org/wiki/Specifications/wm-spec. */
10345 bool
10346 x_wm_supports (struct frame *f, Atom want_atom)
10348 Atom actual_type;
10349 unsigned long actual_size, bytes_remaining;
10350 int i, rc, actual_format;
10351 bool ret;
10352 Window wmcheck_window;
10353 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10354 Window target_window = dpyinfo->root_window;
10355 int max_len = 65536;
10356 Display *dpy = FRAME_X_DISPLAY (f);
10357 unsigned char *tmp_data = NULL;
10358 Atom target_type = XA_WINDOW;
10360 block_input ();
10362 x_catch_errors (dpy);
10363 rc = XGetWindowProperty (dpy, target_window,
10364 dpyinfo->Xatom_net_supporting_wm_check,
10365 0, max_len, False, target_type,
10366 &actual_type, &actual_format, &actual_size,
10367 &bytes_remaining, &tmp_data);
10369 if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
10371 if (tmp_data) XFree (tmp_data);
10372 x_uncatch_errors ();
10373 unblock_input ();
10374 return false;
10377 wmcheck_window = *(Window *) tmp_data;
10378 XFree (tmp_data);
10380 /* Check if window exists. */
10381 XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
10382 if (x_had_errors_p (dpy))
10384 x_uncatch_errors_after_check ();
10385 unblock_input ();
10386 return false;
10389 if (dpyinfo->net_supported_window != wmcheck_window)
10391 /* Window changed, reload atoms */
10392 if (dpyinfo->net_supported_atoms != NULL)
10393 XFree (dpyinfo->net_supported_atoms);
10394 dpyinfo->net_supported_atoms = NULL;
10395 dpyinfo->nr_net_supported_atoms = 0;
10396 dpyinfo->net_supported_window = 0;
10398 target_type = XA_ATOM;
10399 tmp_data = NULL;
10400 rc = XGetWindowProperty (dpy, target_window,
10401 dpyinfo->Xatom_net_supported,
10402 0, max_len, False, target_type,
10403 &actual_type, &actual_format, &actual_size,
10404 &bytes_remaining, &tmp_data);
10406 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
10408 if (tmp_data) XFree (tmp_data);
10409 x_uncatch_errors ();
10410 unblock_input ();
10411 return false;
10414 dpyinfo->net_supported_atoms = (Atom *)tmp_data;
10415 dpyinfo->nr_net_supported_atoms = actual_size;
10416 dpyinfo->net_supported_window = wmcheck_window;
10419 ret = false;
10421 for (i = 0; !ret && i < dpyinfo->nr_net_supported_atoms; ++i)
10422 ret = dpyinfo->net_supported_atoms[i] == want_atom;
10424 x_uncatch_errors ();
10425 unblock_input ();
10427 return ret;
10430 static void
10431 set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
10433 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
10435 x_send_client_event (frame, make_number (0), frame,
10436 dpyinfo->Xatom_net_wm_state,
10437 make_number (32),
10438 /* 1 = add, 0 = remove */
10439 Fcons
10440 (make_number (add),
10441 Fcons
10442 (make_fixnum_or_float (atom),
10443 (value != 0
10444 ? list1 (make_fixnum_or_float (value))
10445 : Qnil))));
10448 void
10449 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10451 Lisp_Object frame;
10452 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10454 XSETFRAME (frame, f);
10456 set_wm_state (frame, !NILP (new_value),
10457 dpyinfo->Xatom_net_wm_state_sticky, None);
10461 * x_set_skip_taskbar:
10463 * Set frame F's `skip-taskbar' parameter. If non-nil, this should
10464 * remove F's icon from the taskbar associated with the display of F's
10465 * window-system window and inhibit switching to F's window via
10466 * <Alt>-<TAB>. If nil, lift these restrictions.
10468 * Some window managers may not honor this parameter.
10470 void
10471 x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10473 if (!EQ (new_value, old_value))
10475 #ifdef USE_GTK
10476 xg_set_skip_taskbar (f, new_value);
10477 #else
10478 Lisp_Object frame;
10479 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10481 XSETFRAME (frame, f);
10482 set_wm_state (frame, !NILP (new_value),
10483 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
10484 #endif /* USE_GTK */
10485 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
10490 * x_set_z_group:
10492 * Set frame F's `z-group' parameter. If `above', F's window-system
10493 * window is displayed above all windows that do not have the `above'
10494 * property set. If nil, F's window is shown below all windows that
10495 * have the `above' property set and above all windows that have the
10496 * `below' property set. If `below', F's window is displayed below all
10497 * windows that do not have the `below' property set.
10499 * Some window managers may not honor this parameter.
10501 void
10502 x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10504 /* We don't care about old_value. The window manager might have
10505 reset the value without telling us. */
10506 Lisp_Object frame;
10507 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10509 XSETFRAME (frame, f);
10511 if (NILP (new_value))
10513 set_wm_state (frame, false,
10514 dpyinfo->Xatom_net_wm_state_above, None);
10515 set_wm_state (frame, false,
10516 dpyinfo->Xatom_net_wm_state_below, None);
10517 FRAME_Z_GROUP (f) = z_group_none;
10519 else if (EQ (new_value, Qabove))
10521 set_wm_state (frame, true,
10522 dpyinfo->Xatom_net_wm_state_above, None);
10523 set_wm_state (frame, false,
10524 dpyinfo->Xatom_net_wm_state_below, None);
10525 FRAME_Z_GROUP (f) = z_group_above;
10527 else if (EQ (new_value, Qbelow))
10529 set_wm_state (frame, false,
10530 dpyinfo->Xatom_net_wm_state_above, None);
10531 set_wm_state (frame, true,
10532 dpyinfo->Xatom_net_wm_state_below, None);
10533 FRAME_Z_GROUP (f) = z_group_below;
10535 else if (EQ (new_value, Qabove_suspended))
10537 set_wm_state (frame, false,
10538 dpyinfo->Xatom_net_wm_state_above, None);
10539 FRAME_Z_GROUP (f) = z_group_above_suspended;
10541 else
10542 error ("Invalid z-group specification");
10546 /* Return the current _NET_WM_STATE.
10547 SIZE_STATE is set to one of the FULLSCREEN_* values.
10548 Set *STICKY to the sticky state.
10550 Return true iff we are not hidden. */
10552 static bool
10553 get_current_wm_state (struct frame *f,
10554 Window window,
10555 int *size_state,
10556 bool *sticky)
10558 unsigned long actual_size;
10559 int i;
10560 bool is_hidden = false;
10561 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10562 long max_len = 65536;
10563 Atom target_type = XA_ATOM;
10564 /* If XCB is available, we can avoid three XSync calls. */
10565 #ifdef USE_XCB
10566 xcb_get_property_cookie_t prop_cookie;
10567 xcb_get_property_reply_t *prop;
10568 xcb_atom_t *reply_data;
10569 #else
10570 Display *dpy = FRAME_X_DISPLAY (f);
10571 unsigned long bytes_remaining;
10572 int rc, actual_format;
10573 Atom actual_type;
10574 unsigned char *tmp_data = NULL;
10575 Atom *reply_data;
10576 #endif
10578 *sticky = false;
10579 *size_state = FULLSCREEN_NONE;
10581 block_input ();
10583 #ifdef USE_XCB
10584 prop_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, window,
10585 dpyinfo->Xatom_net_wm_state,
10586 target_type, 0, max_len);
10587 prop = xcb_get_property_reply (dpyinfo->xcb_connection, prop_cookie, NULL);
10588 if (prop && prop->type == target_type)
10590 int actual_bytes = xcb_get_property_value_length (prop);
10591 eassume (0 <= actual_bytes);
10592 actual_size = actual_bytes / sizeof *reply_data;
10593 reply_data = xcb_get_property_value (prop);
10595 else
10597 actual_size = 0;
10598 is_hidden = FRAME_ICONIFIED_P (f);
10600 #else
10601 x_catch_errors (dpy);
10602 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
10603 0, max_len, False, target_type,
10604 &actual_type, &actual_format, &actual_size,
10605 &bytes_remaining, &tmp_data);
10607 if (rc == Success && actual_type == target_type && ! x_had_errors_p (dpy))
10608 reply_data = (Atom *) tmp_data;
10609 else
10611 actual_size = 0;
10612 is_hidden = FRAME_ICONIFIED_P (f);
10615 x_uncatch_errors ();
10616 #endif
10618 for (i = 0; i < actual_size; ++i)
10620 Atom a = reply_data[i];
10621 if (a == dpyinfo->Xatom_net_wm_state_hidden)
10622 is_hidden = true;
10623 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
10625 if (*size_state == FULLSCREEN_HEIGHT)
10626 *size_state = FULLSCREEN_MAXIMIZED;
10627 else
10628 *size_state = FULLSCREEN_WIDTH;
10630 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
10632 if (*size_state == FULLSCREEN_WIDTH)
10633 *size_state = FULLSCREEN_MAXIMIZED;
10634 else
10635 *size_state = FULLSCREEN_HEIGHT;
10637 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
10638 *size_state = FULLSCREEN_BOTH;
10639 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
10640 *sticky = true;
10643 #ifdef USE_XCB
10644 free (prop);
10645 #else
10646 if (tmp_data) XFree (tmp_data);
10647 #endif
10649 unblock_input ();
10650 return ! is_hidden;
10653 /* Do fullscreen as specified in extended window manager hints */
10655 static bool
10656 do_ewmh_fullscreen (struct frame *f)
10658 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10659 bool have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state);
10660 int cur;
10661 bool dummy;
10663 get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
10665 /* Some window managers don't say they support _NET_WM_STATE, but they do say
10666 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
10667 if (!have_net_atom)
10668 have_net_atom = x_wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
10670 if (have_net_atom && cur != f->want_fullscreen)
10672 Lisp_Object frame;
10674 XSETFRAME (frame, f);
10676 /* Keep number of calls to set_wm_state as low as possible.
10677 Some window managers, or possible Gtk+, hangs when too many
10678 are sent at once. */
10679 switch (f->want_fullscreen)
10681 case FULLSCREEN_BOTH:
10682 if (cur != FULLSCREEN_BOTH)
10683 set_wm_state (frame, true, dpyinfo->Xatom_net_wm_state_fullscreen,
10684 None);
10685 break;
10686 case FULLSCREEN_WIDTH:
10687 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
10689 set_wm_state (frame, false,
10690 dpyinfo->Xatom_net_wm_state_maximized_horz,
10691 dpyinfo->Xatom_net_wm_state_maximized_vert);
10692 set_wm_state (frame, true,
10693 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
10695 else
10697 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
10698 || cur == FULLSCREEN_MAXIMIZED)
10699 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
10700 dpyinfo->Xatom_net_wm_state_maximized_vert);
10701 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
10702 set_wm_state (frame, true,
10703 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
10705 break;
10706 case FULLSCREEN_HEIGHT:
10707 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
10709 set_wm_state (frame, false,
10710 dpyinfo->Xatom_net_wm_state_maximized_horz,
10711 dpyinfo->Xatom_net_wm_state_maximized_vert);
10712 set_wm_state (frame, true,
10713 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
10715 else
10717 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
10718 || cur == FULLSCREEN_MAXIMIZED)
10719 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
10720 dpyinfo->Xatom_net_wm_state_maximized_horz);
10721 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
10722 set_wm_state (frame, true,
10723 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
10725 break;
10726 case FULLSCREEN_MAXIMIZED:
10727 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_BOTH)
10729 set_wm_state (frame, false,
10730 dpyinfo->Xatom_net_wm_state_fullscreen, None);
10731 set_wm_state (frame, true,
10732 dpyinfo->Xatom_net_wm_state_maximized_horz,
10733 dpyinfo->Xatom_net_wm_state_maximized_vert);
10735 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
10737 set_wm_state (frame, false,
10738 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
10739 set_wm_state (frame, true,
10740 dpyinfo->Xatom_net_wm_state_maximized_horz,
10741 dpyinfo->Xatom_net_wm_state_maximized_vert);
10743 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
10745 set_wm_state (frame, false,
10746 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
10747 set_wm_state (frame, true,
10748 dpyinfo->Xatom_net_wm_state_maximized_horz,
10749 dpyinfo->Xatom_net_wm_state_maximized_vert);
10751 else
10753 if (cur == FULLSCREEN_BOTH)
10754 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
10755 None);
10756 else if (cur == FULLSCREEN_HEIGHT)
10757 set_wm_state (frame, true,
10758 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
10759 else if (cur == FULLSCREEN_WIDTH)
10760 set_wm_state (frame, true, None,
10761 dpyinfo->Xatom_net_wm_state_maximized_vert);
10762 else
10763 set_wm_state (frame, true,
10764 dpyinfo->Xatom_net_wm_state_maximized_horz,
10765 dpyinfo->Xatom_net_wm_state_maximized_vert);
10767 break;
10768 case FULLSCREEN_NONE:
10769 if (cur == FULLSCREEN_BOTH)
10770 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
10771 None);
10772 else
10773 set_wm_state (frame, false,
10774 dpyinfo->Xatom_net_wm_state_maximized_horz,
10775 dpyinfo->Xatom_net_wm_state_maximized_vert);
10778 f->want_fullscreen = FULLSCREEN_NONE;
10782 return have_net_atom;
10785 static void
10786 XTfullscreen_hook (struct frame *f)
10788 if (FRAME_VISIBLE_P (f))
10790 block_input ();
10791 x_check_fullscreen (f);
10792 x_sync (f);
10793 unblock_input ();
10798 static bool
10799 x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
10801 int value = FULLSCREEN_NONE;
10802 Lisp_Object lval;
10803 bool sticky = false;
10804 bool not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
10806 lval = Qnil;
10807 switch (value)
10809 case FULLSCREEN_WIDTH:
10810 lval = Qfullwidth;
10811 break;
10812 case FULLSCREEN_HEIGHT:
10813 lval = Qfullheight;
10814 break;
10815 case FULLSCREEN_BOTH:
10816 lval = Qfullboth;
10817 break;
10818 case FULLSCREEN_MAXIMIZED:
10819 lval = Qmaximized;
10820 break;
10823 frame_size_history_add
10824 (f, Qx_handle_net_wm_state, 0, 0,
10825 list2 (get_frame_param (f, Qfullscreen), lval));
10827 store_frame_param (f, Qfullscreen, lval);
10828 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
10830 return not_hidden;
10833 /* Check if we need to resize the frame due to a fullscreen request.
10834 If so needed, resize the frame. */
10835 static void
10836 x_check_fullscreen (struct frame *f)
10838 Lisp_Object lval = Qnil;
10840 if (do_ewmh_fullscreen (f))
10841 return;
10843 if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
10844 return; /* Only fullscreen without WM or with EWM hints (above). */
10846 /* Setting fullscreen to nil doesn't do anything. We could save the
10847 last non-fullscreen size and restore it, but it seems like a
10848 lot of work for this unusual case (no window manager running). */
10850 if (f->want_fullscreen != FULLSCREEN_NONE)
10852 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
10853 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10855 switch (f->want_fullscreen)
10857 /* No difference between these two when there is no WM */
10858 case FULLSCREEN_MAXIMIZED:
10859 lval = Qmaximized;
10860 width = x_display_pixel_width (dpyinfo);
10861 height = x_display_pixel_height (dpyinfo);
10862 break;
10863 case FULLSCREEN_BOTH:
10864 lval = Qfullboth;
10865 width = x_display_pixel_width (dpyinfo);
10866 height = x_display_pixel_height (dpyinfo);
10867 break;
10868 case FULLSCREEN_WIDTH:
10869 lval = Qfullwidth;
10870 width = x_display_pixel_width (dpyinfo);
10871 height = height + FRAME_MENUBAR_HEIGHT (f);
10872 break;
10873 case FULLSCREEN_HEIGHT:
10874 lval = Qfullheight;
10875 height = x_display_pixel_height (dpyinfo);
10876 break;
10877 default:
10878 emacs_abort ();
10881 frame_size_history_add
10882 (f, Qx_check_fullscreen, width, height, Qnil);
10884 x_wm_set_size_hint (f, 0, false);
10886 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10887 width, height);
10889 if (FRAME_VISIBLE_P (f))
10890 x_wait_for_event (f, ConfigureNotify);
10891 else
10893 change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f),
10894 false, true, false, true);
10895 x_sync (f);
10899 /* `x_net_wm_state' might have reset the fullscreen frame parameter,
10900 restore it. */
10901 store_frame_param (f, Qfullscreen, lval);
10904 /* This function is called by x_set_offset to determine whether the window
10905 manager interfered with the positioning of the frame. Type A window
10906 managers position the surrounding window manager decorations a small
10907 amount above and left of the user-supplied position. Type B window
10908 managers position the surrounding window manager decorations at the
10909 user-specified position. If we detect a Type A window manager, we
10910 compensate by moving the window right and down by the proper amount. */
10912 static void
10913 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
10915 int current_left = 0, current_top = 0;
10917 /* x_real_positions returns the left and top offsets of the outermost
10918 window manager window around the frame. */
10920 x_real_positions (f, &current_left, &current_top);
10922 if (current_left != expected_left || current_top != expected_top)
10924 /* It's a "Type A" window manager. */
10926 int adjusted_left;
10927 int adjusted_top;
10929 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
10930 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
10931 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
10933 /* Now fix the mispositioned frame's location. */
10935 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
10936 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
10938 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10939 adjusted_left, adjusted_top);
10941 x_sync_with_move (f, expected_left, expected_top, false);
10943 else
10944 /* It's a "Type B" window manager. We don't have to adjust the
10945 frame's position. */
10947 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
10951 /* Wait for XGetGeometry to return up-to-date position information for a
10952 recently-moved frame. Call this immediately after calling XMoveWindow.
10953 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
10954 frame has been moved to, so we use a fuzzy position comparison instead
10955 of an exact comparison. */
10957 static void
10958 x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
10960 int count = 0;
10962 while (count++ < 50)
10964 int current_left = 0, current_top = 0;
10966 /* In theory, this call to XSync only needs to happen once, but in
10967 practice, it doesn't seem to work, hence the need for the surrounding
10968 loop. */
10970 XSync (FRAME_X_DISPLAY (f), False);
10971 x_real_positions (f, &current_left, &current_top);
10973 if (fuzzy)
10975 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
10976 pixels. */
10978 if (eabs (current_left - left) <= 10
10979 && eabs (current_top - top) <= 40)
10980 return;
10982 else if (current_left == left && current_top == top)
10983 return;
10986 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
10987 will then return up-to-date position info. */
10989 wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
10993 /* Wait for an event on frame F matching EVENTTYPE. */
10994 void
10995 x_wait_for_event (struct frame *f, int eventtype)
10997 int level = interrupt_input_blocked;
10999 fd_set fds;
11000 struct timespec tmo, tmo_at, time_now;
11001 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
11003 f->wait_event_type = eventtype;
11005 /* Set timeout to 0.1 second. Hopefully not noticeable.
11006 Maybe it should be configurable. */
11007 tmo = make_timespec (0, 100 * 1000 * 1000);
11008 tmo_at = timespec_add (current_timespec (), tmo);
11010 while (f->wait_event_type)
11012 pending_signals = true;
11013 totally_unblock_input ();
11014 /* XTread_socket is called after unblock. */
11015 block_input ();
11016 interrupt_input_blocked = level;
11018 FD_ZERO (&fds);
11019 FD_SET (fd, &fds);
11021 time_now = current_timespec ();
11022 if (timespec_cmp (tmo_at, time_now) < 0)
11023 break;
11025 tmo = timespec_sub (tmo_at, time_now);
11026 if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
11027 break; /* Timeout */
11030 f->wait_event_type = 0;
11034 /* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
11035 doesn't have a widget. If CHANGE_GRAVITY, change to
11036 top-left-corner window gravity for this size change and subsequent
11037 size changes. Otherwise leave the window gravity unchanged. */
11039 static void
11040 x_set_window_size_1 (struct frame *f, bool change_gravity,
11041 int width, int height)
11043 int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
11044 int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
11045 int old_width = FRAME_PIXEL_WIDTH (f);
11046 int old_height = FRAME_PIXEL_HEIGHT (f);
11047 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
11049 if (change_gravity)
11050 f->win_gravity = NorthWestGravity;
11051 x_wm_set_size_hint (f, 0, false);
11053 /* When the frame is fullheight and we only want to change the width
11054 or it is fullwidth and we only want to change the height we should
11055 be able to preserve the fullscreen property. However, due to the
11056 fact that we have to send a resize request anyway, the window
11057 manager will abolish it. At least the respective size should
11058 remain unchanged but giving the frame back its normal size will
11059 be broken ... */
11060 if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
11062 frame_size_history_add
11063 (f, Qx_set_window_size_1, width, height,
11064 list2 (make_number (old_height),
11065 make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
11067 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11068 old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f));
11070 else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
11072 frame_size_history_add
11073 (f, Qx_set_window_size_2, width, height,
11074 list2 (make_number (old_width), make_number (pixelwidth)));
11076 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11077 pixelwidth, old_height);
11080 else
11082 frame_size_history_add
11083 (f, Qx_set_window_size_3, width, height,
11084 list3 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
11085 make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
11086 + FRAME_MENUBAR_HEIGHT (f)),
11087 make_number (FRAME_MENUBAR_HEIGHT (f))));
11089 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11090 pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
11091 fullscreen = Qnil;
11096 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11097 receive in the ConfigureNotify event; if we get what we asked
11098 for, then the event won't cause the screen to become garbaged, so
11099 we have to make sure to do it here. */
11100 SET_FRAME_GARBAGED (f);
11102 /* Now, strictly speaking, we can't be sure that this is accurate,
11103 but the window manager will get around to dealing with the size
11104 change request eventually, and we'll hear how it went when the
11105 ConfigureNotify event gets here.
11107 We could just not bother storing any of this information here,
11108 and let the ConfigureNotify event set everything up, but that
11109 might be kind of confusing to the Lisp code, since size changes
11110 wouldn't be reported in the frame parameters until some random
11111 point in the future when the ConfigureNotify event arrives.
11113 Pass true for DELAY since we can't run Lisp code inside of
11114 a BLOCK_INPUT. */
11116 /* But the ConfigureNotify may in fact never arrive, and then this is
11117 not right if the frame is visible. Instead wait (with timeout)
11118 for the ConfigureNotify. */
11119 if (FRAME_VISIBLE_P (f))
11121 x_wait_for_event (f, ConfigureNotify);
11123 if (!NILP (fullscreen))
11124 /* Try to restore fullscreen state. */
11126 store_frame_param (f, Qfullscreen, fullscreen);
11127 x_set_fullscreen (f, fullscreen, fullscreen);
11130 else
11132 change_frame_size (f, width, height, false, true, false, true);
11133 x_sync (f);
11138 /* Call this to change the size of frame F's x-window.
11139 If CHANGE_GRAVITY, change to top-left-corner window gravity
11140 for this size change and subsequent size changes.
11141 Otherwise we leave the window gravity unchanged. */
11143 void
11144 x_set_window_size (struct frame *f, bool change_gravity,
11145 int width, int height, bool pixelwise)
11147 block_input ();
11149 /* The following breaks our calculations. If it's really needed,
11150 think of something else. */
11151 #if false
11152 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11154 int text_width, text_height;
11156 /* When the frame is maximized/fullscreen or running under for
11157 example Xmonad, x_set_window_size_1 will be a no-op.
11158 In that case, the right thing to do is extend rows/width to
11159 the current frame size. We do that first if x_set_window_size_1
11160 turns out to not be a no-op (there is no way to know).
11161 The size will be adjusted again if the frame gets a
11162 ConfigureNotify event as a result of x_set_window_size. */
11163 int pixelh = FRAME_PIXEL_HEIGHT (f);
11164 #ifdef USE_X_TOOLKIT
11165 /* The menu bar is not part of text lines. The tool bar
11166 is however. */
11167 pixelh -= FRAME_MENUBAR_HEIGHT (f);
11168 #endif
11169 text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
11170 text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
11172 change_frame_size (f, text_width, text_height, false, true, false, true);
11174 #endif
11176 /* Pixelize width and height, if necessary. */
11177 if (! pixelwise)
11179 width = width * FRAME_COLUMN_WIDTH (f);
11180 height = height * FRAME_LINE_HEIGHT (f);
11183 #ifdef USE_GTK
11184 if (FRAME_GTK_WIDGET (f))
11185 xg_frame_set_char_size (f, width, height);
11186 else
11187 x_set_window_size_1 (f, change_gravity, width, height);
11188 #else /* not USE_GTK */
11189 x_set_window_size_1 (f, change_gravity, width, height);
11190 x_clear_under_internal_border (f);
11191 #endif /* not USE_GTK */
11193 /* If cursor was outside the new size, mark it as off. */
11194 mark_window_cursors_off (XWINDOW (f->root_window));
11196 /* Clear out any recollection of where the mouse highlighting was,
11197 since it might be in a place that's outside the new frame size.
11198 Actually checking whether it is outside is a pain in the neck,
11199 so don't try--just let the highlighting be done afresh with new size. */
11200 cancel_mouse_face (f);
11202 unblock_input ();
11204 do_pending_window_change (false);
11207 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11209 void
11210 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
11212 block_input ();
11214 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11215 0, 0, 0, 0, pix_x, pix_y);
11216 unblock_input ();
11219 /* Raise frame F. */
11221 void
11222 x_raise_frame (struct frame *f)
11224 block_input ();
11225 if (FRAME_VISIBLE_P (f))
11226 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11227 XFlush (FRAME_X_DISPLAY (f));
11228 unblock_input ();
11231 /* Lower frame F. */
11233 static void
11234 x_lower_frame (struct frame *f)
11236 if (FRAME_VISIBLE_P (f))
11238 block_input ();
11239 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11240 XFlush (FRAME_X_DISPLAY (f));
11241 unblock_input ();
11245 /* Request focus with XEmbed */
11247 void
11248 xembed_request_focus (struct frame *f)
11250 /* See XEmbed Protocol Specification at
11251 http://freedesktop.org/wiki/Specifications/xembed-spec */
11252 if (FRAME_VISIBLE_P (f))
11253 xembed_send_message (f, CurrentTime,
11254 XEMBED_REQUEST_FOCUS, 0, 0, 0);
11257 /* Activate frame with Extended Window Manager Hints */
11259 void
11260 x_ewmh_activate_frame (struct frame *f)
11262 /* See Window Manager Specification/Extended Window Manager Hints at
11263 http://freedesktop.org/wiki/Specifications/wm-spec */
11265 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11267 if (FRAME_VISIBLE_P (f) && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
11269 Lisp_Object frame;
11270 XSETFRAME (frame, f);
11271 x_send_client_event (frame, make_number (0), frame,
11272 dpyinfo->Xatom_net_active_window,
11273 make_number (32),
11274 list2i (1, dpyinfo->last_user_time));
11278 static void
11279 XTframe_raise_lower (struct frame *f, bool raise_flag)
11281 if (raise_flag)
11282 x_raise_frame (f);
11283 else
11284 x_lower_frame (f);
11287 /* XEmbed implementation. */
11289 #if defined USE_X_TOOLKIT || ! defined USE_GTK
11291 /* XEmbed implementation. */
11293 #define XEMBED_VERSION 0
11295 static void
11296 xembed_set_info (struct frame *f, enum xembed_info flags)
11298 unsigned long data[2];
11299 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11301 data[0] = XEMBED_VERSION;
11302 data[1] = flags;
11304 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11305 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
11306 32, PropModeReplace, (unsigned char *) data, 2);
11308 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
11310 static void
11311 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
11312 long int detail, long int data1, long int data2)
11314 XEvent event;
11316 event.xclient.type = ClientMessage;
11317 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
11318 event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
11319 event.xclient.format = 32;
11320 event.xclient.data.l[0] = t;
11321 event.xclient.data.l[1] = msg;
11322 event.xclient.data.l[2] = detail;
11323 event.xclient.data.l[3] = data1;
11324 event.xclient.data.l[4] = data2;
11326 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
11327 False, NoEventMask, &event);
11328 XSync (FRAME_X_DISPLAY (f), False);
11331 /* Change of visibility. */
11333 /* This function sends the request to make the frame visible, but may
11334 return before it the frame's visibility is changed. */
11336 void
11337 x_make_frame_visible (struct frame *f)
11339 if (FRAME_PARENT_FRAME (f))
11341 if (!FRAME_VISIBLE_P (f))
11343 block_input ();
11344 #ifdef USE_GTK
11345 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11346 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11347 f->left_pos, f->top_pos);
11348 #else
11349 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11350 #endif
11351 unblock_input ();
11353 SET_FRAME_VISIBLE (f, true);
11354 SET_FRAME_ICONIFIED (f, false);
11356 return;
11359 block_input ();
11361 x_set_bitmap_icon (f);
11363 if (! FRAME_VISIBLE_P (f))
11365 /* We test asked_for_visible here to make sure we don't
11366 call x_set_offset a second time
11367 if we get to x_make_frame_visible a second time
11368 before the window gets really visible. */
11369 if (! FRAME_ICONIFIED_P (f)
11370 && ! FRAME_X_EMBEDDED_P (f)
11371 && ! f->output_data.x->asked_for_visible)
11372 x_set_offset (f, f->left_pos, f->top_pos, 0);
11374 f->output_data.x->asked_for_visible = true;
11376 if (! EQ (Vx_no_window_manager, Qt))
11377 x_wm_set_window_state (f, NormalState);
11378 #ifdef USE_X_TOOLKIT
11379 if (FRAME_X_EMBEDDED_P (f))
11380 xembed_set_info (f, XEMBED_MAPPED);
11381 else
11383 /* This was XtPopup, but that did nothing for an iconified frame. */
11384 XtMapWidget (f->output_data.x->widget);
11386 #else /* not USE_X_TOOLKIT */
11387 #ifdef USE_GTK
11388 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11389 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
11390 #else
11391 if (FRAME_X_EMBEDDED_P (f))
11392 xembed_set_info (f, XEMBED_MAPPED);
11393 else
11394 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11395 #endif /* not USE_GTK */
11396 #endif /* not USE_X_TOOLKIT */
11399 XFlush (FRAME_X_DISPLAY (f));
11401 /* Synchronize to ensure Emacs knows the frame is visible
11402 before we do anything else. We do this loop with input not blocked
11403 so that incoming events are handled. */
11405 /* This must be before UNBLOCK_INPUT
11406 since events that arrive in response to the actions above
11407 will set it when they are handled. */
11408 bool previously_visible = f->output_data.x->has_been_visible;
11410 int original_left = f->left_pos;
11411 int original_top = f->top_pos;
11413 /* This must come after we set COUNT. */
11414 unblock_input ();
11416 /* We unblock here so that arriving X events are processed. */
11418 /* Now move the window back to where it was "supposed to be".
11419 But don't do it if the gravity is negative.
11420 When the gravity is negative, this uses a position
11421 that is 3 pixels too low. Perhaps that's really the border width.
11423 Don't do this if the window has never been visible before,
11424 because the window manager may choose the position
11425 and we don't want to override it. */
11427 if (!FRAME_VISIBLE_P (f)
11428 && !FRAME_ICONIFIED_P (f)
11429 && !FRAME_X_EMBEDDED_P (f)
11430 && !FRAME_PARENT_FRAME (f)
11431 && f->win_gravity == NorthWestGravity
11432 && previously_visible)
11434 Drawable rootw;
11435 int x, y;
11436 unsigned int width, height, border, depth;
11438 block_input ();
11440 /* On some window managers (such as FVWM) moving an existing
11441 window, even to the same place, causes the window manager
11442 to introduce an offset. This can cause the window to move
11443 to an unexpected location. Check the geometry (a little
11444 slow here) and then verify that the window is in the right
11445 place. If the window is not in the right place, move it
11446 there, and take the potential window manager hit. */
11447 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11448 &rootw, &x, &y, &width, &height, &border, &depth);
11450 if (original_left != x || original_top != y)
11451 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11452 original_left, original_top);
11454 unblock_input ();
11459 /* Change from mapped state to withdrawn state. */
11461 /* Make the frame visible (mapped and not iconified). */
11463 void
11464 x_make_frame_invisible (struct frame *f)
11466 Window window;
11468 /* Use the frame's outermost window, not the one we normally draw on. */
11469 window = FRAME_OUTER_WINDOW (f);
11471 /* Don't keep the highlight on an invisible frame. */
11472 if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
11473 FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
11475 block_input ();
11477 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11478 that the current position of the window is user-specified, rather than
11479 program-specified, so that when the window is mapped again, it will be
11480 placed at the same location, without forcing the user to position it
11481 by hand again (they have already done that once for this window.) */
11482 x_wm_set_size_hint (f, 0, true);
11484 #ifdef USE_GTK
11485 if (FRAME_GTK_OUTER_WIDGET (f))
11486 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
11487 else
11488 #else
11489 if (FRAME_X_EMBEDDED_P (f))
11490 xembed_set_info (f, 0);
11491 else
11492 #endif
11494 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11495 DefaultScreen (FRAME_X_DISPLAY (f))))
11497 unblock_input ();
11498 error ("Can't notify window manager of window withdrawal");
11501 x_sync (f);
11503 /* We can't distinguish this from iconification
11504 just by the event that we get from the server.
11505 So we can't win using the usual strategy of letting
11506 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11507 and synchronize with the server to make sure we agree. */
11508 SET_FRAME_VISIBLE (f, 0);
11509 SET_FRAME_ICONIFIED (f, false);
11511 unblock_input ();
11514 /* Change window state from mapped to iconified. */
11516 void
11517 x_iconify_frame (struct frame *f)
11519 #ifdef USE_X_TOOLKIT
11520 int result;
11521 #endif
11523 /* Don't keep the highlight on an invisible frame. */
11524 if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
11525 FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
11527 if (FRAME_ICONIFIED_P (f))
11528 return;
11530 block_input ();
11532 x_set_bitmap_icon (f);
11534 #if defined (USE_GTK)
11535 if (FRAME_GTK_OUTER_WIDGET (f))
11537 if (! FRAME_VISIBLE_P (f))
11538 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11540 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
11541 SET_FRAME_VISIBLE (f, 0);
11542 SET_FRAME_ICONIFIED (f, true);
11543 unblock_input ();
11544 return;
11546 #endif
11548 #ifdef USE_X_TOOLKIT
11550 if (! FRAME_VISIBLE_P (f))
11552 if (! EQ (Vx_no_window_manager, Qt))
11553 x_wm_set_window_state (f, IconicState);
11554 /* This was XtPopup, but that did nothing for an iconified frame. */
11555 XtMapWidget (f->output_data.x->widget);
11556 /* The server won't give us any event to indicate
11557 that an invisible frame was changed to an icon,
11558 so we have to record it here. */
11559 SET_FRAME_VISIBLE (f, 0);
11560 SET_FRAME_ICONIFIED (f, true);
11561 unblock_input ();
11562 return;
11565 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11566 XtWindow (f->output_data.x->widget),
11567 DefaultScreen (FRAME_X_DISPLAY (f)));
11568 unblock_input ();
11570 if (!result)
11571 error ("Can't notify window manager of iconification");
11573 SET_FRAME_ICONIFIED (f, true);
11574 SET_FRAME_VISIBLE (f, 0);
11576 block_input ();
11577 XFlush (FRAME_X_DISPLAY (f));
11578 unblock_input ();
11579 #else /* not USE_X_TOOLKIT */
11581 /* Make sure the X server knows where the window should be positioned,
11582 in case the user deiconifies with the window manager. */
11583 if (! FRAME_VISIBLE_P (f)
11584 && ! FRAME_ICONIFIED_P (f)
11585 && ! FRAME_X_EMBEDDED_P (f))
11586 x_set_offset (f, f->left_pos, f->top_pos, 0);
11588 /* Since we don't know which revision of X we're running, we'll use both
11589 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11591 /* X11R4: send a ClientMessage to the window manager using the
11592 WM_CHANGE_STATE type. */
11594 XEvent msg;
11596 msg.xclient.window = FRAME_X_WINDOW (f);
11597 msg.xclient.type = ClientMessage;
11598 msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
11599 msg.xclient.format = 32;
11600 msg.xclient.data.l[0] = IconicState;
11602 if (! XSendEvent (FRAME_X_DISPLAY (f),
11603 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11604 False,
11605 SubstructureRedirectMask | SubstructureNotifyMask,
11606 &msg))
11608 unblock_input ();
11609 error ("Can't notify window manager of iconification");
11613 /* X11R3: set the initial_state field of the window manager hints to
11614 IconicState. */
11615 x_wm_set_window_state (f, IconicState);
11617 if (!FRAME_VISIBLE_P (f))
11619 /* If the frame was withdrawn, before, we must map it. */
11620 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11623 SET_FRAME_ICONIFIED (f, true);
11624 SET_FRAME_VISIBLE (f, 0);
11626 XFlush (FRAME_X_DISPLAY (f));
11627 unblock_input ();
11628 #endif /* not USE_X_TOOLKIT */
11632 /* Free X resources of frame F. */
11634 void
11635 x_free_frame_resources (struct frame *f)
11637 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11638 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
11639 #ifdef USE_X_TOOLKIT
11640 Lisp_Object bar;
11641 struct scroll_bar *b;
11642 #endif
11644 block_input ();
11646 /* If a display connection is dead, don't try sending more
11647 commands to the X server. */
11648 if (dpyinfo->display)
11650 /* Always exit with visible pointer to avoid weird issue
11651 with Xfixes (Bug#17609). */
11652 if (f->pointer_invisible)
11653 FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0);
11655 /* We must free faces before destroying windows because some
11656 font-driver (e.g. xft) access a window while finishing a
11657 face. */
11658 free_frame_faces (f);
11659 tear_down_x_back_buffer (f);
11661 if (f->output_data.x->icon_desc)
11662 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
11664 #ifdef USE_X_TOOLKIT
11665 /* Explicitly destroy the scroll bars of the frame. Without
11666 this, we get "BadDrawable" errors from the toolkit later on,
11667 presumably from expose events generated for the disappearing
11668 toolkit scroll bars. */
11669 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
11671 b = XSCROLL_BAR (bar);
11672 x_scroll_bar_remove (b);
11674 #endif
11676 #ifdef HAVE_X_I18N
11677 if (FRAME_XIC (f))
11678 free_frame_xic (f);
11679 #endif
11681 x_free_cr_resources (f);
11682 #ifdef USE_X_TOOLKIT
11683 if (f->output_data.x->widget)
11685 XtDestroyWidget (f->output_data.x->widget);
11686 f->output_data.x->widget = NULL;
11688 /* Tooltips don't have widgets, only a simple X window, even if
11689 we are using a toolkit. */
11690 else if (FRAME_X_WINDOW (f))
11691 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11693 free_frame_menubar (f);
11695 if (f->shell_position)
11696 xfree (f->shell_position);
11697 #else /* !USE_X_TOOLKIT */
11699 #ifdef USE_GTK
11700 xg_free_frame_widgets (f);
11701 #endif /* USE_GTK */
11703 tear_down_x_back_buffer (f);
11704 if (FRAME_X_WINDOW (f))
11705 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11706 #endif /* !USE_X_TOOLKIT */
11708 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
11709 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
11710 unload_color (f, f->output_data.x->cursor_pixel);
11711 unload_color (f, f->output_data.x->cursor_foreground_pixel);
11712 unload_color (f, f->output_data.x->border_pixel);
11713 unload_color (f, f->output_data.x->mouse_pixel);
11715 if (f->output_data.x->scroll_bar_background_pixel != -1)
11716 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
11717 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
11718 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
11719 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
11720 /* Scrollbar shadow colors. */
11721 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
11722 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
11723 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
11724 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
11725 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
11726 if (f->output_data.x->white_relief.pixel != -1)
11727 unload_color (f, f->output_data.x->white_relief.pixel);
11728 if (f->output_data.x->black_relief.pixel != -1)
11729 unload_color (f, f->output_data.x->black_relief.pixel);
11731 x_free_gcs (f);
11733 /* Free extra GCs allocated by x_setup_relief_colors. */
11734 if (f->output_data.x->white_relief.gc)
11736 XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
11737 f->output_data.x->white_relief.gc = 0;
11739 if (f->output_data.x->black_relief.gc)
11741 XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
11742 f->output_data.x->black_relief.gc = 0;
11745 /* Free cursors. */
11746 if (f->output_data.x->text_cursor != 0)
11747 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
11748 if (f->output_data.x->nontext_cursor != 0)
11749 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
11750 if (f->output_data.x->modeline_cursor != 0)
11751 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->modeline_cursor);
11752 if (f->output_data.x->hand_cursor != 0)
11753 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hand_cursor);
11754 if (f->output_data.x->hourglass_cursor != 0)
11755 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
11756 if (f->output_data.x->horizontal_drag_cursor != 0)
11757 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
11758 if (f->output_data.x->vertical_drag_cursor != 0)
11759 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
11761 XFlush (FRAME_X_DISPLAY (f));
11764 xfree (f->output_data.x->saved_menu_event);
11765 xfree (f->output_data.x);
11766 f->output_data.x = NULL;
11768 if (f == dpyinfo->x_focus_frame)
11769 dpyinfo->x_focus_frame = 0;
11770 if (f == dpyinfo->x_focus_event_frame)
11771 dpyinfo->x_focus_event_frame = 0;
11772 if (f == dpyinfo->x_highlight_frame)
11773 dpyinfo->x_highlight_frame = 0;
11774 if (f == hlinfo->mouse_face_mouse_frame)
11775 reset_mouse_highlight (hlinfo);
11777 unblock_input ();
11781 /* Destroy the X window of frame F. */
11783 static void
11784 x_destroy_window (struct frame *f)
11786 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
11788 /* If a display connection is dead, don't try sending more
11789 commands to the X server. */
11790 if (dpyinfo->display != 0)
11791 x_free_frame_resources (f);
11793 dpyinfo->reference_count--;
11797 /* Setting window manager hints. */
11799 /* Set the normal size hints for the window manager, for frame F.
11800 FLAGS is the flags word to use--or 0 meaning preserve the flags
11801 that the window now has.
11802 If USER_POSITION, set the USPosition
11803 flag (this is useful when FLAGS is 0).
11804 The GTK version is in gtkutils.c. */
11806 #ifndef USE_GTK
11807 void
11808 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
11810 XSizeHints size_hints;
11811 Window window = FRAME_OUTER_WINDOW (f);
11813 if (!window)
11814 return;
11816 #ifdef USE_X_TOOLKIT
11817 if (f->output_data.x->widget)
11819 widget_update_wm_size_hints (f->output_data.x->widget);
11820 return;
11822 #endif
11824 /* Setting PMaxSize caused various problems. */
11825 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
11827 size_hints.x = f->left_pos;
11828 size_hints.y = f->top_pos;
11830 size_hints.width = FRAME_PIXEL_WIDTH (f);
11831 size_hints.height = FRAME_PIXEL_HEIGHT (f);
11833 size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
11834 size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
11836 size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
11837 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
11838 size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
11839 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
11841 /* Calculate the base and minimum sizes. */
11843 int base_width, base_height;
11845 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
11846 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
11848 /* The window manager uses the base width hints to calculate the
11849 current number of rows and columns in the frame while
11850 resizing; min_width and min_height aren't useful for this
11851 purpose, since they might not give the dimensions for a
11852 zero-row, zero-column frame. */
11854 size_hints.flags |= PBaseSize;
11855 size_hints.base_width = base_width;
11856 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
11857 size_hints.min_width = base_width;
11858 size_hints.min_height = base_height;
11861 /* If we don't need the old flags, we don't need the old hint at all. */
11862 if (flags)
11864 size_hints.flags |= flags;
11865 goto no_read;
11869 XSizeHints hints; /* Sometimes I hate X Windows... */
11870 long supplied_return;
11871 int value;
11873 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
11874 &supplied_return);
11876 if (flags)
11877 size_hints.flags |= flags;
11878 else
11880 if (value == 0)
11881 hints.flags = 0;
11882 if (hints.flags & PSize)
11883 size_hints.flags |= PSize;
11884 if (hints.flags & PPosition)
11885 size_hints.flags |= PPosition;
11886 if (hints.flags & USPosition)
11887 size_hints.flags |= USPosition;
11888 if (hints.flags & USSize)
11889 size_hints.flags |= USSize;
11893 no_read:
11895 #ifdef PWinGravity
11896 size_hints.win_gravity = f->win_gravity;
11897 size_hints.flags |= PWinGravity;
11899 if (user_position)
11901 size_hints.flags &= ~ PPosition;
11902 size_hints.flags |= USPosition;
11904 #endif /* PWinGravity */
11906 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
11908 #endif /* not USE_GTK */
11910 /* Used for IconicState or NormalState */
11912 static void
11913 x_wm_set_window_state (struct frame *f, int state)
11915 #ifdef USE_X_TOOLKIT
11916 Arg al[1];
11918 XtSetArg (al[0], XtNinitialState, state);
11919 XtSetValues (f->output_data.x->widget, al, 1);
11920 #else /* not USE_X_TOOLKIT */
11921 Window window = FRAME_X_WINDOW (f);
11923 f->output_data.x->wm_hints.flags |= StateHint;
11924 f->output_data.x->wm_hints.initial_state = state;
11926 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11927 #endif /* not USE_X_TOOLKIT */
11930 static void
11931 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
11933 Pixmap icon_pixmap, icon_mask;
11935 #if !defined USE_X_TOOLKIT && !defined USE_GTK
11936 Window window = FRAME_OUTER_WINDOW (f);
11937 #endif
11939 if (pixmap_id > 0)
11941 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
11942 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
11943 icon_mask = x_bitmap_mask (f, pixmap_id);
11944 f->output_data.x->wm_hints.icon_mask = icon_mask;
11946 else
11948 /* It seems there is no way to turn off use of an icon
11949 pixmap. */
11950 return;
11954 #ifdef USE_GTK
11956 xg_set_frame_icon (f, icon_pixmap, icon_mask);
11957 return;
11960 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
11963 Arg al[1];
11964 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
11965 XtSetValues (f->output_data.x->widget, al, 1);
11966 XtSetArg (al[0], XtNiconMask, icon_mask);
11967 XtSetValues (f->output_data.x->widget, al, 1);
11970 #else /* not USE_X_TOOLKIT && not USE_GTK */
11972 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
11973 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11975 #endif /* not USE_X_TOOLKIT && not USE_GTK */
11978 void
11979 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
11981 Window window = FRAME_OUTER_WINDOW (f);
11983 f->output_data.x->wm_hints.flags |= IconPositionHint;
11984 f->output_data.x->wm_hints.icon_x = icon_x;
11985 f->output_data.x->wm_hints.icon_y = icon_y;
11987 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11991 /***********************************************************************
11992 Fonts
11993 ***********************************************************************/
11995 #ifdef GLYPH_DEBUG
11997 /* Check that FONT is valid on frame F. It is if it can be found in F's
11998 font table. */
12000 static void
12001 x_check_font (struct frame *f, struct font *font)
12003 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
12004 if (font->driver->check)
12005 eassert (font->driver->check (f, font) == 0);
12008 #endif /* GLYPH_DEBUG */
12011 /***********************************************************************
12012 Initialization
12013 ***********************************************************************/
12015 #ifdef USE_X_TOOLKIT
12016 static XrmOptionDescRec emacs_options[] = {
12017 {(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, NULL},
12018 {(char *) "-iconic", (char *) ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12020 {(char *) "-internal-border-width",
12021 (char *) "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12022 {(char *) "-ib", (char *) "*EmacsScreen.internalBorderWidth",
12023 XrmoptionSepArg, NULL},
12024 {(char *) "-T", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12025 {(char *) "-wn", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12026 {(char *) "-title", (char *) "*EmacsShell.title", XrmoptionSepArg, NULL},
12027 {(char *) "-iconname", (char *) "*EmacsShell.iconName",
12028 XrmoptionSepArg, NULL},
12029 {(char *) "-in", (char *) "*EmacsShell.iconName", XrmoptionSepArg, NULL},
12030 {(char *) "-mc", (char *) "*pointerColor", XrmoptionSepArg, NULL},
12031 {(char *) "-cr", (char *) "*cursorColor", XrmoptionSepArg, NULL}
12034 /* Whether atimer for Xt timeouts is activated or not. */
12036 static bool x_timeout_atimer_activated_flag;
12038 #endif /* USE_X_TOOLKIT */
12040 static int x_initialized;
12042 /* Test whether two display-name strings agree up to the dot that separates
12043 the screen number from the server number. */
12044 static bool
12045 same_x_server (const char *name1, const char *name2)
12047 bool seen_colon = false;
12048 Lisp_Object sysname = Fsystem_name ();
12049 const char *system_name = SSDATA (sysname);
12050 ptrdiff_t system_name_length = SBYTES (sysname);
12051 ptrdiff_t length_until_period = 0;
12053 while (system_name[length_until_period] != 0
12054 && system_name[length_until_period] != '.')
12055 length_until_period++;
12057 /* Treat `unix' like an empty host name. */
12058 if (! strncmp (name1, "unix:", 5))
12059 name1 += 4;
12060 if (! strncmp (name2, "unix:", 5))
12061 name2 += 4;
12062 /* Treat this host's name like an empty host name. */
12063 if (! strncmp (name1, system_name, system_name_length)
12064 && name1[system_name_length] == ':')
12065 name1 += system_name_length;
12066 if (! strncmp (name2, system_name, system_name_length)
12067 && name2[system_name_length] == ':')
12068 name2 += system_name_length;
12069 /* Treat this host's domainless name like an empty host name. */
12070 if (! strncmp (name1, system_name, length_until_period)
12071 && name1[length_until_period] == ':')
12072 name1 += length_until_period;
12073 if (! strncmp (name2, system_name, length_until_period)
12074 && name2[length_until_period] == ':')
12075 name2 += length_until_period;
12077 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12079 if (*name1 == ':')
12080 seen_colon = true;
12081 if (seen_colon && *name1 == '.')
12082 return true;
12084 return (seen_colon
12085 && (*name1 == '.' || *name1 == '\0')
12086 && (*name2 == '.' || *name2 == '\0'));
12089 /* Count number of set bits in mask and number of bits to shift to
12090 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
12091 to 5. */
12092 static void
12093 get_bits_and_offset (unsigned long mask, int *bits, int *offset)
12095 int nr = 0;
12096 int off = 0;
12098 while (!(mask & 1))
12100 off++;
12101 mask >>= 1;
12104 while (mask & 1)
12106 nr++;
12107 mask >>= 1;
12110 *offset = off;
12111 *bits = nr;
12114 /* Return true iff display DISPLAY is available for use.
12115 But don't permanently open it, just test its availability. */
12117 bool
12118 x_display_ok (const char *display)
12120 /* XOpenDisplay fails if it gets a signal. Block SIGIO which may arrive. */
12121 unrequest_sigio ();
12122 Display *dpy = XOpenDisplay (display);
12123 request_sigio ();
12124 if (!dpy)
12125 return false;
12126 XCloseDisplay (dpy);
12127 return true;
12130 #ifdef USE_GTK
12131 static void
12132 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
12133 const gchar *msg, gpointer user_data)
12135 if (!strstr (msg, "g_set_prgname"))
12136 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
12138 #endif
12140 /* Create invisible cursor on X display referred by DPYINFO. */
12142 static Cursor
12143 make_invisible_cursor (struct x_display_info *dpyinfo)
12145 Display *dpy = dpyinfo->display;
12146 static char const no_data[] = { 0 };
12147 Pixmap pix;
12148 XColor col;
12149 Cursor c = 0;
12151 x_catch_errors (dpy);
12152 pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
12153 if (! x_had_errors_p (dpy) && pix != None)
12155 Cursor pixc;
12156 col.pixel = 0;
12157 col.red = col.green = col.blue = 0;
12158 col.flags = DoRed | DoGreen | DoBlue;
12159 pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
12160 if (! x_had_errors_p (dpy) && pixc != None)
12161 c = pixc;
12162 XFreePixmap (dpy, pix);
12165 x_uncatch_errors ();
12167 return c;
12170 /* True if DPY supports Xfixes extension >= 4. */
12172 static bool
12173 x_probe_xfixes_extension (Display *dpy)
12175 #ifdef HAVE_XFIXES
12176 int major, minor;
12177 return XFixesQueryVersion (dpy, &major, &minor) && major >= 4;
12178 #else
12179 return false;
12180 #endif /* HAVE_XFIXES */
12183 /* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
12185 static void
12186 xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
12188 #ifdef HAVE_XFIXES
12189 if (invisible)
12190 XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12191 else
12192 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12193 f->pointer_invisible = invisible;
12194 #else
12195 emacs_abort ();
12196 #endif /* HAVE_XFIXES */
12199 /* Toggle mouse pointer visibility on frame F by using invisible cursor. */
12201 static void
12202 x_toggle_visible_pointer (struct frame *f, bool invisible)
12204 eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0);
12205 if (invisible)
12206 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12207 FRAME_DISPLAY_INFO (f)->invisible_cursor);
12208 else
12209 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12210 f->output_data.x->current_cursor);
12211 f->pointer_invisible = invisible;
12214 /* Setup pointer blanking, prefer Xfixes if available. */
12216 static void
12217 x_setup_pointer_blanking (struct x_display_info *dpyinfo)
12219 /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
12220 X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */
12221 if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo->display))
12222 dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer;
12223 else
12225 dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer;
12226 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
12230 /* Current X display connection identifier. Incremented for each next
12231 connection established. */
12232 static unsigned x_display_id;
12234 /* Open a connection to X display DISPLAY_NAME, and return
12235 the structure that describes the open display.
12236 If we cannot contact the display, return null. */
12238 struct x_display_info *
12239 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
12241 Display *dpy;
12242 struct terminal *terminal;
12243 struct x_display_info *dpyinfo;
12244 XrmDatabase xrdb;
12245 #ifdef USE_XCB
12246 xcb_connection_t *xcb_conn;
12247 #endif
12249 block_input ();
12251 if (!x_initialized)
12253 x_initialize ();
12254 ++x_initialized;
12257 if (! x_display_ok (SSDATA (display_name)))
12258 error ("Display %s can't be opened", SSDATA (display_name));
12260 #ifdef USE_GTK
12262 #define NUM_ARGV 10
12263 int argc;
12264 char *argv[NUM_ARGV];
12265 char **argv2 = argv;
12266 guint id;
12268 if (x_initialized++ > 1)
12270 xg_display_open (SSDATA (display_name), &dpy);
12272 else
12274 static char display_opt[] = "--display";
12275 static char name_opt[] = "--name";
12277 for (argc = 0; argc < NUM_ARGV; ++argc)
12278 argv[argc] = 0;
12280 argc = 0;
12281 argv[argc++] = initial_argv[0];
12283 if (! NILP (display_name))
12285 argv[argc++] = display_opt;
12286 argv[argc++] = SSDATA (display_name);
12289 argv[argc++] = name_opt;
12290 argv[argc++] = resource_name;
12292 XSetLocaleModifiers ("");
12294 /* Work around GLib bug that outputs a faulty warning. See
12295 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
12296 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
12297 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
12299 /* NULL window -> events for all windows go to our function.
12300 Call before gtk_init so Gtk+ event filters comes after our. */
12301 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
12303 /* gtk_init does set_locale. Fix locale before and after. */
12304 fixup_locale ();
12305 unrequest_sigio (); /* See comment in x_display_ok. */
12306 gtk_init (&argc, &argv2);
12307 request_sigio ();
12308 fixup_locale ();
12310 g_log_remove_handler ("GLib", id);
12312 xg_initialize ();
12314 dpy = DEFAULT_GDK_DISPLAY ();
12316 #if ! GTK_CHECK_VERSION (2, 90, 0)
12317 /* Load our own gtkrc if it exists. */
12319 const char *file = "~/.emacs.d/gtkrc";
12320 Lisp_Object s, abs_file;
12322 s = build_string (file);
12323 abs_file = Fexpand_file_name (s, Qnil);
12325 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
12326 gtk_rc_parse (SSDATA (abs_file));
12328 #endif
12330 XSetErrorHandler (x_error_handler);
12331 XSetIOErrorHandler (x_io_error_quitter);
12334 #else /* not USE_GTK */
12335 #ifdef USE_X_TOOLKIT
12336 /* weiner@footloose.sps.mot.com reports that this causes
12337 errors with X11R5:
12338 X protocol error: BadAtom (invalid Atom parameter)
12339 on protocol request 18skiloaf.
12340 So let's not use it until R6. */
12341 #ifdef HAVE_X11XTR6
12342 XtSetLanguageProc (NULL, NULL, NULL);
12343 #endif
12346 int argc = 0;
12347 char *argv[3];
12349 argv[0] = (char *) "";
12350 argc = 1;
12351 if (xrm_option)
12353 argv[argc++] = (char *) "-xrm";
12354 argv[argc++] = xrm_option;
12356 turn_on_atimers (false);
12357 unrequest_sigio (); /* See comment in x_display_ok. */
12358 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
12359 resource_name, EMACS_CLASS,
12360 emacs_options, XtNumber (emacs_options),
12361 &argc, argv);
12362 request_sigio ();
12363 turn_on_atimers (true);
12365 #ifdef HAVE_X11XTR6
12366 /* I think this is to compensate for XtSetLanguageProc. */
12367 fixup_locale ();
12368 #endif
12371 #else /* not USE_X_TOOLKIT */
12372 XSetLocaleModifiers ("");
12373 unrequest_sigio (); /* See comment in x_display_ok. */
12374 dpy = XOpenDisplay (SSDATA (display_name));
12375 request_sigio ();
12376 #endif /* not USE_X_TOOLKIT */
12377 #endif /* not USE_GTK*/
12379 /* Detect failure. */
12380 if (dpy == 0)
12382 unblock_input ();
12383 return 0;
12386 #ifdef USE_XCB
12387 xcb_conn = XGetXCBConnection (dpy);
12388 if (xcb_conn == 0)
12390 #ifdef USE_GTK
12391 xg_display_close (dpy);
12392 #else
12393 #ifdef USE_X_TOOLKIT
12394 XtCloseDisplay (dpy);
12395 #else
12396 XCloseDisplay (dpy);
12397 #endif
12398 #endif /* ! USE_GTK */
12400 unblock_input ();
12401 return 0;
12403 #endif
12405 /* We have definitely succeeded. Record the new connection. */
12407 dpyinfo = xzalloc (sizeof *dpyinfo);
12408 terminal = x_create_terminal (dpyinfo);
12411 struct x_display_info *share;
12413 for (share = x_display_list; share; share = share->next)
12414 if (same_x_server (SSDATA (XCAR (share->name_list_element)),
12415 SSDATA (display_name)))
12416 break;
12417 if (share)
12418 terminal->kboard = share->terminal->kboard;
12419 else
12421 terminal->kboard = allocate_kboard (Qx);
12423 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12425 char *vendor = ServerVendor (dpy);
12427 /* Temporarily hide the partially initialized terminal. */
12428 terminal_list = terminal->next_terminal;
12429 unblock_input ();
12430 kset_system_key_alist
12431 (terminal->kboard,
12432 call1 (Qvendor_specific_keysyms,
12433 vendor ? build_string (vendor) : empty_unibyte_string));
12434 block_input ();
12435 terminal->next_terminal = terminal_list;
12436 terminal_list = terminal;
12439 /* Don't let the initial kboard remain current longer than necessary.
12440 That would cause problems if a file loaded on startup tries to
12441 prompt in the mini-buffer. */
12442 if (current_kboard == initial_kboard)
12443 current_kboard = terminal->kboard;
12445 terminal->kboard->reference_count++;
12448 /* Put this display on the chain. */
12449 dpyinfo->next = x_display_list;
12450 x_display_list = dpyinfo;
12452 dpyinfo->name_list_element = Fcons (display_name, Qnil);
12453 dpyinfo->display = dpy;
12454 dpyinfo->connection = ConnectionNumber (dpyinfo->display);
12455 #ifdef USE_XCB
12456 dpyinfo->xcb_connection = xcb_conn;
12457 #endif
12459 /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
12460 dpyinfo->smallest_font_height = 1;
12461 dpyinfo->smallest_char_width = 1;
12463 /* Set the name of the terminal. */
12464 terminal->name = xlispstrdup (display_name);
12466 #if false
12467 XSetAfterFunction (x_current_display, x_trace_wire);
12468 #endif
12470 Lisp_Object system_name = Fsystem_name ();
12471 ptrdiff_t nbytes;
12472 if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
12473 &nbytes))
12474 memory_full (SIZE_MAX);
12475 dpyinfo->x_id = ++x_display_id;
12476 dpyinfo->x_id_name = xmalloc (nbytes);
12477 char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
12478 *nametail++ = '@';
12479 lispstpcpy (nametail, system_name);
12481 /* Figure out which modifier bits mean what. */
12482 x_find_modifier_meanings (dpyinfo);
12484 /* Get the scroll bar cursor. */
12485 #ifdef USE_GTK
12486 /* We must create a GTK cursor, it is required for GTK widgets. */
12487 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
12488 #endif /* USE_GTK */
12490 dpyinfo->vertical_scroll_bar_cursor
12491 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12493 dpyinfo->horizontal_scroll_bar_cursor
12494 = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
12496 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12497 resource_name, EMACS_CLASS);
12498 #ifdef HAVE_XRMSETDATABASE
12499 XrmSetDatabase (dpyinfo->display, xrdb);
12500 #else
12501 dpyinfo->display->db = xrdb;
12502 #endif
12503 /* Put the rdb where we can find it in a way that works on
12504 all versions. */
12505 dpyinfo->xrdb = xrdb;
12507 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12508 DefaultScreen (dpyinfo->display));
12509 select_visual (dpyinfo);
12510 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
12511 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12512 dpyinfo->icon_bitmap_id = -1;
12513 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
12515 reset_mouse_highlight (&dpyinfo->mouse_highlight);
12517 /* See if we can construct pixel values from RGB values. */
12518 if (dpyinfo->visual->class == TrueColor)
12520 get_bits_and_offset (dpyinfo->visual->red_mask,
12521 &dpyinfo->red_bits, &dpyinfo->red_offset);
12522 get_bits_and_offset (dpyinfo->visual->blue_mask,
12523 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
12524 get_bits_and_offset (dpyinfo->visual->green_mask,
12525 &dpyinfo->green_bits, &dpyinfo->green_offset);
12528 /* See if a private colormap is requested. */
12529 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
12531 if (dpyinfo->visual->class == PseudoColor)
12533 AUTO_STRING (privateColormap, "privateColormap");
12534 AUTO_STRING (PrivateColormap, "PrivateColormap");
12535 Lisp_Object value
12536 = display_x_get_resource (dpyinfo, privateColormap,
12537 PrivateColormap, Qnil, Qnil);
12538 if (STRINGP (value)
12539 && (!strcmp (SSDATA (value), "true")
12540 || !strcmp (SSDATA (value), "on")))
12541 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
12544 else
12545 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
12546 dpyinfo->visual, AllocNone);
12548 #ifdef HAVE_XDBE
12549 dpyinfo->supports_xdbe = false;
12550 int xdbe_major;
12551 int xdbe_minor;
12552 if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
12553 dpyinfo->supports_xdbe = true;
12554 #endif
12556 #ifdef HAVE_XFT
12558 /* If we are using Xft, the following precautions should be made:
12560 1. Make sure that the Xrender extension is added before the Xft one.
12561 Otherwise, the close-display hook set by Xft is called after the one
12562 for Xrender, and the former tries to re-add the latter. This results
12563 in inconsistency of internal states and leads to X protocol error when
12564 one reconnects to the same X server (Bug#1696).
12566 2. Check dpi value in X resources. It is better we use it as well,
12567 since Xft will use it, as will all Gnome applications. If our real DPI
12568 is smaller or larger than the one Xft uses, our font will look smaller
12569 or larger than other for other applications, even if it is the same
12570 font name (monospace-10 for example). */
12572 int event_base, error_base;
12573 char *v;
12574 double d;
12576 XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
12578 v = XGetDefault (dpyinfo->display, "Xft", "dpi");
12579 if (v != NULL && sscanf (v, "%lf", &d) == 1)
12580 dpyinfo->resy = dpyinfo->resx = d;
12582 #endif
12584 if (dpyinfo->resy < 1)
12586 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
12587 double pixels = DisplayHeight (dpyinfo->display, screen_number);
12588 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
12589 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
12590 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
12591 pixels = DisplayWidth (dpyinfo->display, screen_number);
12592 mm = DisplayWidthMM (dpyinfo->display, screen_number);
12593 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
12594 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
12598 static const struct
12600 const char *name;
12601 int offset;
12602 } atom_refs[] = {
12603 #define ATOM_REFS_INIT(string, member) \
12604 { string, offsetof (struct x_display_info, member) },
12605 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
12606 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
12607 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
12608 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
12609 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
12610 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
12611 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
12612 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
12613 ATOM_REFS_INIT ("Editres", Xatom_editres)
12614 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
12615 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
12616 ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
12617 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
12618 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
12619 ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
12620 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
12621 ATOM_REFS_INIT ("INCR", Xatom_INCR)
12622 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
12623 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
12624 ATOM_REFS_INIT ("NULL", Xatom_NULL)
12625 ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
12626 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
12627 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
12628 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
12629 /* For properties of font. */
12630 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
12631 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
12632 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
12633 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
12634 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
12635 /* Ghostscript support. */
12636 ATOM_REFS_INIT ("DONE", Xatom_DONE)
12637 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
12638 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
12639 ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
12640 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
12641 /* EWMH */
12642 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
12643 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
12644 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
12645 Xatom_net_wm_state_maximized_horz)
12646 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
12647 Xatom_net_wm_state_maximized_vert)
12648 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
12649 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
12650 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
12651 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
12652 Xatom_net_window_type_tooltip)
12653 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
12654 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
12655 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
12656 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
12657 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
12658 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
12659 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
12660 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
12661 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
12662 /* Session management */
12663 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
12664 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
12665 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
12666 ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
12667 ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
12668 ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
12671 int i;
12672 enum { atom_count = ARRAYELTS (atom_refs) };
12673 /* 1 for _XSETTINGS_SN. */
12674 enum { total_atom_count = 1 + atom_count };
12675 Atom atoms_return[total_atom_count];
12676 char *atom_names[total_atom_count];
12677 static char const xsettings_fmt[] = "_XSETTINGS_S%d";
12678 char xsettings_atom_name[sizeof xsettings_fmt - 2
12679 + INT_STRLEN_BOUND (int)];
12681 for (i = 0; i < atom_count; i++)
12682 atom_names[i] = (char *) atom_refs[i].name;
12684 /* Build _XSETTINGS_SN atom name. */
12685 sprintf (xsettings_atom_name, xsettings_fmt,
12686 XScreenNumberOfScreen (dpyinfo->screen));
12687 atom_names[i] = xsettings_atom_name;
12689 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
12690 False, atoms_return);
12692 for (i = 0; i < atom_count; i++)
12693 *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
12695 /* Manually copy last atom. */
12696 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
12699 dpyinfo->x_dnd_atoms_size = 8;
12700 dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
12701 * dpyinfo->x_dnd_atoms_size);
12702 dpyinfo->gray
12703 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12704 gray_bits, gray_width, gray_height,
12705 1, 0, 1);
12707 x_setup_pointer_blanking (dpyinfo);
12709 #ifdef HAVE_X_I18N
12710 xim_initialize (dpyinfo, resource_name);
12711 #endif
12713 xsettings_initialize (dpyinfo);
12715 /* This is only needed for distinguishing keyboard and process input. */
12716 if (dpyinfo->connection != 0)
12717 add_keyboard_wait_descriptor (dpyinfo->connection);
12719 #ifdef F_SETOWN
12720 fcntl (dpyinfo->connection, F_SETOWN, getpid ());
12721 #endif /* ! defined (F_SETOWN) */
12723 if (interrupt_input)
12724 init_sigio (dpyinfo->connection);
12726 #ifdef USE_LUCID
12728 XrmValue d, fr, to;
12729 Font font;
12731 dpy = dpyinfo->display;
12732 d.addr = (XPointer)&dpy;
12733 d.size = sizeof (Display *);
12734 fr.addr = (char *) XtDefaultFont;
12735 fr.size = sizeof (XtDefaultFont);
12736 to.size = sizeof (Font *);
12737 to.addr = (XPointer)&font;
12738 x_catch_errors (dpy);
12739 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
12740 emacs_abort ();
12741 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
12742 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
12743 /* Do not free XFontStruct returned by the above call to XQueryFont.
12744 This leads to X protocol errors at XtCloseDisplay (Bug#18403). */
12745 x_uncatch_errors ();
12747 #endif
12749 /* See if we should run in synchronous mode. This is useful
12750 for debugging X code. */
12752 AUTO_STRING (synchronous, "synchronous");
12753 AUTO_STRING (Synchronous, "Synchronous");
12754 Lisp_Object value = display_x_get_resource (dpyinfo, synchronous,
12755 Synchronous, Qnil, Qnil);
12756 if (STRINGP (value)
12757 && (!strcmp (SSDATA (value), "true")
12758 || !strcmp (SSDATA (value), "on")))
12759 XSynchronize (dpyinfo->display, True);
12763 AUTO_STRING (useXIM, "useXIM");
12764 AUTO_STRING (UseXIM, "UseXIM");
12765 Lisp_Object value = display_x_get_resource (dpyinfo, useXIM, UseXIM,
12766 Qnil, Qnil);
12767 #ifdef USE_XIM
12768 if (STRINGP (value)
12769 && (!strcmp (SSDATA (value), "false")
12770 || !strcmp (SSDATA (value), "off")))
12771 use_xim = false;
12772 #else
12773 if (STRINGP (value)
12774 && (!strcmp (SSDATA (value), "true")
12775 || !strcmp (SSDATA (value), "on")))
12776 use_xim = true;
12777 #endif
12780 #ifdef HAVE_X_SM
12781 /* Only do this for the very first display in the Emacs session.
12782 Ignore X session management when Emacs was first started on a
12783 tty or started as a daemon. */
12784 if (terminal->id == 1 && ! IS_DAEMON)
12785 x_session_initialize (dpyinfo);
12786 #endif
12788 #ifdef USE_CAIRO
12789 x_extension_initialize (dpyinfo);
12790 #endif
12792 unblock_input ();
12794 return dpyinfo;
12797 /* Get rid of display DPYINFO, deleting all frames on it,
12798 and without sending any more commands to the X server. */
12800 static void
12801 x_delete_display (struct x_display_info *dpyinfo)
12803 struct terminal *t;
12804 struct color_name_cache_entry *color_entry, *next_color_entry;
12806 /* Close all frames and delete the generic struct terminal for this
12807 X display. */
12808 for (t = terminal_list; t; t = t->next_terminal)
12809 if (t->type == output_x_window && t->display_info.x == dpyinfo)
12811 #ifdef HAVE_X_SM
12812 /* Close X session management when we close its display. */
12813 if (t->id == 1 && x_session_have_connection ())
12814 x_session_close ();
12815 #endif
12816 delete_terminal (t);
12817 break;
12820 if (next_noop_dpyinfo == dpyinfo)
12821 next_noop_dpyinfo = dpyinfo->next;
12823 if (x_display_list == dpyinfo)
12824 x_display_list = dpyinfo->next;
12825 else
12827 struct x_display_info *tail;
12829 for (tail = x_display_list; tail; tail = tail->next)
12830 if (tail->next == dpyinfo)
12831 tail->next = tail->next->next;
12834 for (color_entry = dpyinfo->color_names;
12835 color_entry;
12836 color_entry = next_color_entry)
12838 next_color_entry = color_entry->next;
12839 xfree (color_entry->name);
12840 xfree (color_entry);
12843 xfree (dpyinfo->x_id_name);
12844 xfree (dpyinfo->x_dnd_atoms);
12845 xfree (dpyinfo->color_cells);
12846 xfree (dpyinfo);
12849 #ifdef USE_X_TOOLKIT
12851 /* Atimer callback function for TIMER. Called every 0.1s to process
12852 Xt timeouts, if needed. We must avoid calling XtAppPending as
12853 much as possible because that function does an implicit XFlush
12854 that slows us down. */
12856 static void
12857 x_process_timeouts (struct atimer *timer)
12859 block_input ();
12860 x_timeout_atimer_activated_flag = false;
12861 if (toolkit_scroll_bar_interaction || popup_activated ())
12863 while (XtAppPending (Xt_app_con) & XtIMTimer)
12864 XtAppProcessEvent (Xt_app_con, XtIMTimer);
12865 /* Reactivate the atimer for next time. */
12866 x_activate_timeout_atimer ();
12868 unblock_input ();
12871 /* Install an asynchronous timer that processes Xt timeout events
12872 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
12873 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
12874 function whenever these variables are set. This is necessary
12875 because some widget sets use timeouts internally, for example the
12876 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
12877 processed, these widgets don't behave normally. */
12879 void
12880 x_activate_timeout_atimer (void)
12882 block_input ();
12883 if (!x_timeout_atimer_activated_flag)
12885 struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
12886 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
12887 x_timeout_atimer_activated_flag = true;
12889 unblock_input ();
12892 #endif /* USE_X_TOOLKIT */
12895 /* Set up use of X before we make the first connection. */
12897 static struct redisplay_interface x_redisplay_interface =
12899 x_frame_parm_handlers,
12900 x_produce_glyphs,
12901 x_write_glyphs,
12902 x_insert_glyphs,
12903 x_clear_end_of_line,
12904 x_scroll_run,
12905 x_after_update_window_line,
12906 x_update_window_begin,
12907 x_update_window_end,
12908 x_flip_and_flush,
12909 x_clear_window_mouse_face,
12910 x_get_glyph_overhangs,
12911 x_fix_overlapping_area,
12912 x_draw_fringe_bitmap,
12913 #ifdef USE_CAIRO
12914 x_cr_define_fringe_bitmap,
12915 x_cr_destroy_fringe_bitmap,
12916 #else
12917 0, /* define_fringe_bitmap */
12918 0, /* destroy_fringe_bitmap */
12919 #endif
12920 x_compute_glyph_string_overhangs,
12921 x_draw_glyph_string,
12922 x_define_frame_cursor,
12923 x_clear_frame_area,
12924 x_draw_window_cursor,
12925 x_draw_vertical_window_border,
12926 x_draw_window_divider,
12927 x_shift_glyphs_for_insert, /* Never called; see comment in function. */
12928 x_show_hourglass,
12929 x_hide_hourglass
12933 /* This function is called when the last frame on a display is deleted. */
12934 void
12935 x_delete_terminal (struct terminal *terminal)
12937 struct x_display_info *dpyinfo = terminal->display_info.x;
12939 /* Protect against recursive calls. delete_frame in
12940 delete_terminal calls us back when it deletes our last frame. */
12941 if (!terminal->name)
12942 return;
12944 block_input ();
12945 #ifdef HAVE_X_I18N
12946 /* We must close our connection to the XIM server before closing the
12947 X display. */
12948 if (dpyinfo->xim)
12949 xim_close_dpy (dpyinfo);
12950 #endif
12952 /* Normally, the display is available... */
12953 if (dpyinfo->display)
12955 x_destroy_all_bitmaps (dpyinfo);
12956 XSetCloseDownMode (dpyinfo->display, DestroyAll);
12958 /* Whether or not XCloseDisplay destroys the associated resource
12959 database depends on the version of libX11. To avoid both
12960 crash and memory leak, we dissociate the database from the
12961 display and then destroy dpyinfo->xrdb ourselves.
12963 Unfortunately, the above strategy does not work in some
12964 situations due to a bug in newer versions of libX11: because
12965 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
12966 dpy->db is NULL, XCloseDisplay destroys the associated
12967 database whereas it has not been created by XGetDefault
12968 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
12969 don't destroy the database here in order to avoid the crash
12970 in the above situations for now, though that may cause memory
12971 leaks in other situations. */
12972 #if false
12973 #ifdef HAVE_XRMSETDATABASE
12974 XrmSetDatabase (dpyinfo->display, NULL);
12975 #else
12976 dpyinfo->display->db = NULL;
12977 #endif
12978 /* We used to call XrmDestroyDatabase from x_delete_display, but
12979 some older versions of libX11 crash if we call it after
12980 closing all the displays. */
12981 XrmDestroyDatabase (dpyinfo->xrdb);
12982 #endif
12984 #ifdef USE_GTK
12985 xg_display_close (dpyinfo->display);
12986 #else
12987 #ifdef USE_X_TOOLKIT
12988 XtCloseDisplay (dpyinfo->display);
12989 #else
12990 XCloseDisplay (dpyinfo->display);
12991 #endif
12992 #endif /* ! USE_GTK */
12993 /* Do not close the connection here because it's already closed
12994 by X(t)CloseDisplay (Bug#18403). */
12995 dpyinfo->display = NULL;
12998 /* ...but if called from x_connection_closed, the display may already
12999 be closed and dpyinfo->display was set to 0 to indicate that. Since
13000 X server is most likely gone, explicit close is the only reliable
13001 way to continue and avoid Bug#19147. */
13002 else if (dpyinfo->connection >= 0)
13003 emacs_close (dpyinfo->connection);
13005 /* No more input on this descriptor. */
13006 delete_keyboard_wait_descriptor (dpyinfo->connection);
13007 /* Mark as dead. */
13008 dpyinfo->connection = -1;
13010 x_delete_display (dpyinfo);
13011 unblock_input ();
13014 /* Create a struct terminal, initialize it with the X11 specific
13015 functions and make DISPLAY->TERMINAL point to it. */
13017 static struct terminal *
13018 x_create_terminal (struct x_display_info *dpyinfo)
13020 struct terminal *terminal;
13022 terminal = create_terminal (output_x_window, &x_redisplay_interface);
13024 terminal->display_info.x = dpyinfo;
13025 dpyinfo->terminal = terminal;
13027 /* kboard is initialized in x_term_init. */
13029 terminal->clear_frame_hook = x_clear_frame;
13030 terminal->ins_del_lines_hook = x_ins_del_lines;
13031 terminal->delete_glyphs_hook = x_delete_glyphs;
13032 terminal->ring_bell_hook = XTring_bell;
13033 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
13034 terminal->update_begin_hook = x_update_begin;
13035 terminal->update_end_hook = x_update_end;
13036 terminal->read_socket_hook = XTread_socket;
13037 terminal->frame_up_to_date_hook = XTframe_up_to_date;
13038 terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
13039 terminal->mouse_position_hook = XTmouse_position;
13040 terminal->frame_rehighlight_hook = XTframe_rehighlight;
13041 terminal->frame_raise_lower_hook = XTframe_raise_lower;
13042 terminal->fullscreen_hook = XTfullscreen_hook;
13043 terminal->menu_show_hook = x_menu_show;
13044 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
13045 terminal->popup_dialog_hook = xw_popup_dialog;
13046 #endif
13047 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13048 terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
13049 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13050 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
13051 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
13052 terminal->delete_frame_hook = x_destroy_window;
13053 terminal->delete_terminal_hook = x_delete_terminal;
13054 /* Other hooks are NULL by default. */
13056 return terminal;
13059 static void
13060 x_initialize (void)
13062 baud_rate = 19200;
13064 x_noop_count = 0;
13065 any_help_event_p = false;
13066 ignore_next_mouse_click_timeout = 0;
13068 #ifdef USE_GTK
13069 current_count = -1;
13070 #endif
13072 /* Try to use interrupt input; if we can't, then start polling. */
13073 Fset_input_interrupt_mode (Qt);
13075 #if THREADS_ENABLED
13076 /* This must be called before any other Xlib routines. */
13077 if (XInitThreads () == 0)
13078 fprintf (stderr,
13079 "Warning: An error occurred initializing X11 thread support!\n");
13080 #endif
13082 #ifdef USE_X_TOOLKIT
13083 XtToolkitInitialize ();
13085 Xt_app_con = XtCreateApplicationContext ();
13087 /* Register a converter from strings to pixels, which uses
13088 Emacs' color allocation infrastructure. */
13089 XtAppSetTypeConverter (Xt_app_con,
13090 XtRString, XtRPixel, cvt_string_to_pixel,
13091 cvt_string_to_pixel_args,
13092 XtNumber (cvt_string_to_pixel_args),
13093 XtCacheByDisplay, cvt_pixel_dtor);
13095 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13096 #endif
13098 #ifdef USE_TOOLKIT_SCROLL_BARS
13099 #ifndef USE_GTK
13100 xaw3d_arrow_scroll = False;
13101 xaw3d_pick_top = True;
13102 #endif
13103 #endif
13105 #ifdef USE_CAIRO
13106 x_cr_init_fringe (&x_redisplay_interface);
13107 #endif
13109 /* Note that there is no real way portable across R3/R4 to get the
13110 original error handler. */
13111 XSetErrorHandler (x_error_handler);
13112 XSetIOErrorHandler (x_io_error_quitter);
13115 #ifdef USE_GTK
13116 void
13117 init_xterm (void)
13119 /* Emacs can handle only core input events, so make sure
13120 Gtk doesn't use Xinput or Xinput2 extensions. */
13121 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
13123 #endif
13125 void
13126 syms_of_xterm (void)
13128 x_error_message = NULL;
13130 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
13131 DEFSYM (Qlatin_1, "latin-1");
13133 #ifdef USE_GTK
13134 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
13135 staticpro (&xg_default_icon_file);
13137 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
13138 #endif
13140 DEFVAR_BOOL ("x-use-underline-position-properties",
13141 x_use_underline_position_properties,
13142 doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
13143 A value of nil means ignore them. If you encounter fonts with bogus
13144 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13145 to 4.1, set this to nil. You can also use `underline-minimum-offset'
13146 to override the font's UNDERLINE_POSITION for small font display
13147 sizes. */);
13148 x_use_underline_position_properties = true;
13150 DEFVAR_BOOL ("x-underline-at-descent-line",
13151 x_underline_at_descent_line,
13152 doc: /* Non-nil means to draw the underline at the same place as the descent line.
13153 A value of nil means to draw the underline according to the value of the
13154 variable `x-use-underline-position-properties', which is usually at the
13155 baseline level. The default value is nil. */);
13156 x_underline_at_descent_line = false;
13158 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
13159 x_mouse_click_focus_ignore_position,
13160 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
13161 This variable is only used when the window manager requires that you
13162 click on a frame to select it (give it focus). In that case, a value
13163 of nil, means that the selected window and cursor position changes to
13164 reflect the mouse click position, while a non-nil value means that the
13165 selected window or cursor position is preserved. */);
13166 x_mouse_click_focus_ignore_position = false;
13168 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
13169 doc: /* Which toolkit scroll bars Emacs uses, if any.
13170 A value of nil means Emacs doesn't use toolkit scroll bars.
13171 With the X Window system, the value is a symbol describing the
13172 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
13173 With MS Windows or Nextstep, the value is t. */);
13174 #ifdef USE_TOOLKIT_SCROLL_BARS
13175 #ifdef USE_MOTIF
13176 Vx_toolkit_scroll_bars = intern_c_string ("motif");
13177 #elif defined HAVE_XAW3D
13178 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
13179 #elif USE_GTK
13180 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
13181 #else
13182 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
13183 #endif
13184 #else
13185 Vx_toolkit_scroll_bars = Qnil;
13186 #endif
13188 DEFSYM (Qmodifier_value, "modifier-value");
13189 DEFSYM (Qctrl, "ctrl");
13190 Fput (Qctrl, Qmodifier_value, make_number (ctrl_modifier));
13191 DEFSYM (Qalt, "alt");
13192 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
13193 DEFSYM (Qhyper, "hyper");
13194 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
13195 DEFSYM (Qmeta, "meta");
13196 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
13197 DEFSYM (Qsuper, "super");
13198 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
13200 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
13201 doc: /* Which keys Emacs uses for the ctrl modifier.
13202 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13203 `super'. For example, `ctrl' means use the Ctrl_L and Ctrl_R keysyms.
13204 The default is nil, which is the same as `ctrl'. */);
13205 Vx_ctrl_keysym = Qnil;
13207 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
13208 doc: /* Which keys Emacs uses for the alt modifier.
13209 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13210 `super'. For example, `alt' means use the Alt_L and Alt_R keysyms.
13211 The default is nil, which is the same as `alt'. */);
13212 Vx_alt_keysym = Qnil;
13214 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
13215 doc: /* Which keys Emacs uses for the hyper modifier.
13216 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13217 `super'. For example, `hyper' means use the Hyper_L and Hyper_R
13218 keysyms. The default is nil, which is the same as `hyper'. */);
13219 Vx_hyper_keysym = Qnil;
13221 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
13222 doc: /* Which keys Emacs uses for the meta modifier.
13223 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13224 `super'. For example, `meta' means use the Meta_L and Meta_R keysyms.
13225 The default is nil, which is the same as `meta'. */);
13226 Vx_meta_keysym = Qnil;
13228 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
13229 doc: /* Which keys Emacs uses for the super modifier.
13230 This should be one of the symbols `ctrl', `alt', `hyper', `meta',
13231 `super'. For example, `super' means use the Super_L and Super_R
13232 keysyms. The default is nil, which is the same as `super'. */);
13233 Vx_super_keysym = Qnil;
13235 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
13236 doc: /* Hash table of character codes indexed by X keysym codes. */);
13237 Vx_keysym_table = make_hash_table (hashtest_eql, 900,
13238 DEFAULT_REHASH_SIZE,
13239 DEFAULT_REHASH_THRESHOLD,
13240 Qnil, false);
13242 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
13243 x_frame_normalize_before_maximize,
13244 doc: /* Non-nil means normalize frame before maximizing.
13245 If this variable is t, Emacs first asks the window manager to give the
13246 frame its normal size, and only then the final state, whenever changing
13247 from a full-height, full-width or full-both state to the maximized one
13248 or when changing from the maximized to the full-height or full-width
13249 state.
13251 Set this variable only if your window manager cannot handle the
13252 transition between the various maximization states. */);
13253 x_frame_normalize_before_maximize = false;
13255 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
13256 doc: /* Non-nil means rely on gtk_window_move to set frame positions.
13257 If this variable is t (the default), the GTK build uses the function
13258 gtk_window_move to set or store frame positions and disables some time
13259 consuming frame position adjustments. */);
13260 x_gtk_use_window_move = true;