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. */
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. */
36 #include <X11/cursorfont.h>
38 /* If we have Xfixes extension, use it for pointer blanking. */
40 #include <X11/extensions/Xfixes.h>
43 /* Using Xft implies that XRender is available. */
45 #include <X11/extensions/Xrender.h>
49 #include <X11/extensions/Xdbe.h>
52 /* Load sys/types.h if not already loaded.
53 In some systems loading it twice is suicidal. */
55 #include <sys/types.h>
58 #include <sys/ioctl.h>
65 #include "character.h"
67 #include "composite.h"
69 #include "dispextern.h"
72 #include "termhooks.h"
75 #include "emacs-icon.h"
81 #include "xsettings.h"
82 #include "sysselect.h"
86 #include <X11/Shell.h>
94 #include <X11/Xproto.h>
98 #if defined (USE_LUCID) || defined (USE_MOTIF)
99 #include "../lwlib/xlwmenu.h"
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 */
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 */
121 #define XtNpickTop "pickTop"
122 #endif /* !XtNpickTop */
123 #endif /* !USE_MOTIF */
124 #endif /* USE_TOOLKIT_SCROLL_BARS */
126 #endif /* USE_X_TOOLKIT */
130 #ifndef XtNinitialState
131 #define XtNinitialState "initialState"
135 #include "bitmaps/gray.xbm"
138 #include <X11/XKBlib.h>
141 /* Default to using XIM if available. */
145 bool use_xim
= false; /* configure --without-xim */
148 /* Non-zero means that a HELP_EVENT has been generated since Emacs
151 static bool any_help_event_p
;
153 /* This is a chain of structures for all the X displays currently in
156 struct x_display_info
*x_display_list
;
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
;
180 /* The name of the Emacs icon file. */
181 static Lisp_Object xg_default_icon_file
;
184 /* Some functions take this as char *, not const char *. */
185 static char emacs_class
[] = EMACS_CLASS
;
189 XEMBED_MAPPED
= 1 << 0
194 XEMBED_EMBEDDED_NOTIFY
= 0,
195 XEMBED_WINDOW_ACTIVATE
= 1,
196 XEMBED_WINDOW_DEACTIVATE
= 2,
197 XEMBED_REQUEST_FOCUS
= 3,
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
*,
225 static void x_horizontal_scroll_bar_report_motion (struct frame
**, Lisp_Object
*,
226 enum scroll_bar_part
*,
227 Lisp_Object
*, Lisp_Object
*,
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
*);
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. */
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
))
257 XFlush (FRAME_X_DISPLAY (f
));
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
269 #define XFlush(DISPLAY) (void) 0
272 /***********************************************************************
274 ***********************************************************************/
278 /* This is a function useful for recording debugging information about
279 the sequence of occurrences in this file. */
287 struct record event_record
[100];
289 int event_record_index
;
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
++;
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
);
314 XExtData
**head
, *ext_data
;
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
)
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
;
335 x_extension_initialize (struct x_display_info
*dpyinfo
)
337 XExtCodes
*ext_codes
= XAddExtension (dpyinfo
->display
);
339 dpyinfo
->ext_codes
= ext_codes
;
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
;
356 x_begin_cr_clip (struct frame
*f
, GC gc
)
358 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
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
);
375 cr
= cairo_create (FRAME_CR_SURFACE (f
));
376 FRAME_CR_CONTEXT (f
) = cr
;
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
)
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
);
401 x_end_cr_clip (struct frame
*f
)
403 cairo_restore (FRAME_CR_CONTEXT (f
));
407 x_set_cr_source_with_gc_foreground (struct frame
*f
, GC gc
)
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);
420 x_set_cr_source_with_gc_background (struct frame
*f
, GC gc
)
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;
438 x_cr_define_fringe_bitmap (int which
, unsigned short *bits
, int h
, int wd
)
441 cairo_surface_t
*surface
;
443 cairo_pattern_t
*pattern
;
445 if (which
>= 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
)
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
];
466 cairo_surface_mark_dirty (surface
);
467 pattern
= cairo_pattern_create_for_surface (surface
);
468 cairo_surface_destroy (surface
);
472 fringe_bmp
[which
] = pattern
;
476 x_cr_destroy_fringe_bitmap (int which
)
478 if (which
>= max_fringe_bmp
)
481 if (fringe_bmp
[which
])
484 cairo_pattern_destroy (fringe_bmp
[which
]);
487 fringe_bmp
[which
] = 0;
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
)
496 cairo_matrix_t matrix
;
497 cairo_surface_t
*surface
;
498 cairo_format_t format
;
500 cr
= x_begin_cr_clip (f
, gc
);
502 cairo_rectangle (cr
, dest_x
, dest_y
, width
, height
);
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
);
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
);
521 x_set_cr_source_with_gc_foreground (f
, gc
);
522 cairo_mask (cr
, image
);
528 x_cr_draw_frame (cairo_t
*cr
, struct frame
*f
)
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
,
546 Lisp_Object
*acc
= (Lisp_Object
*) closure
;
548 *acc
= Fcons (make_unibyte_string ((char const *) data
, length
), *acc
);
550 return CAIRO_STATUS_SUCCESS
;
554 x_cr_destroy (Lisp_Object arg
)
556 cairo_t
*cr
= (cairo_t
*) XSAVE_POINTER (arg
, 0);
564 x_cr_export_frames (Lisp_Object frames
, cairo_surface_type_t surface_type
)
567 cairo_surface_t
*surface
;
570 void (*surface_set_size_func
) (cairo_surface_t
*, double, double) = NULL
;
571 Lisp_Object acc
= Qnil
;
572 ptrdiff_t 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
);
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
,
588 surface_set_size_func
= cairo_pdf_surface_set_size
;
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
);
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
,
602 surface_set_size_func
= cairo_ps_surface_set_size
;
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
,
614 cr
= cairo_create (surface
);
615 cairo_surface_destroy (surface
);
616 record_unwind_protect (x_cr_destroy
, make_save_ptr (cr
));
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
;
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
);
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
);
651 unbind_to (count
, Qnil
);
653 return CALLN (Fapply
, intern ("concat"), Fnreverse (acc
));
656 #endif /* USE_CAIRO */
659 x_free_cr_resources (struct frame
*f
)
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
));
671 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
675 cairo_surface_t
*surface
= cairo_get_target (cr
);
677 if (cairo_surface_get_type (surface
) == CAIRO_SURFACE_TYPE_XLIB
)
680 FRAME_CR_CONTEXT (f
) = NULL
;
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
);
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
);
704 x_reset_clip_rectangles (struct frame
*f
, GC gc
)
706 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
709 struct x_gc_ext_data
*gc_ext
= x_gc_get_ext_data (f
, gc
, 0);
712 gc_ext
->n_clip_rects
= 0;
718 x_fill_rectangle (struct frame
*f
, GC gc
, int x
, int y
, int width
, int height
)
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
);
729 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
730 gc
, x
, y
, width
, height
);
735 x_draw_rectangle (struct frame
*f
, GC gc
, int x
, int y
, int width
, int height
)
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);
747 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
748 gc
, x
, y
, width
, height
);
753 x_clear_window (struct frame
*f
)
758 cr
= x_begin_cr_clip (f
, NULL
);
759 x_set_cr_source_with_gc_background (f
, f
->output_data
.x
->normal_gc
);
763 if (FRAME_X_DOUBLE_BUFFERED_P (f
))
764 x_clear_area (f
, 0, 0, FRAME_PIXEL_WIDTH (f
), FRAME_PIXEL_HEIGHT (f
));
766 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
772 x_fill_trapezoid_for_relief (struct frame
*f
, GC gc
, int x
, int y
,
773 int width
, int height
, int top_p
)
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
);
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 */
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
)
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
;
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
;
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
);
824 cairo_rectangle (cr
, x
, y
, width
, height
);
830 x_draw_horizontal_wave (struct frame
*f
, GC gc
, int x
, int y
,
831 int width
, int height
, int wave_length
)
834 double dx
= wave_length
, dy
= height
- 1;
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
);
844 xoffset
= x
% (wave_length
* 2);
846 xoffset
= wave_length
* 2;
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
;
859 cairo_move_to (cr
, x
- xoffset
+ 0.5, y
+ 0.5);
862 cairo_rel_line_to (cr
, dx
, dy
);
865 cairo_set_line_width (cr
, 1);
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
)
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
)
897 unsigned int nchildren
;
900 if (XQueryTree (dpy
, win
, &root
, &wi
, &children
, &nchildren
))
909 #define OPAQUE 0xffffffff
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
);
918 double alpha_min
= 1.0;
922 if (dpyinfo
->x_highlight_frame
== f
)
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;
934 else if (alpha
> 1.0)
936 else if (0.0 <= alpha
&& alpha
< alpha_min
&& alpha_min
<= 1.0)
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
);
952 XChangeProperty (dpy
, parent
, dpyinfo
->Xatom_net_wm_window_opacity
,
953 XA_CARDINAL
, 32, PropModeReplace
,
954 (unsigned char *) &opac
, 1);
957 /* return unless necessary */
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
,
969 if (rc
== Success
&& actual
!= None
)
971 unsigned long value
= *(unsigned long *)data
;
981 XChangeProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
982 XA_CARDINAL
, 32, PropModeReplace
,
983 (unsigned char *) &opac
, 1);
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. */
998 x_update_begin (struct frame
*f
)
1001 if (! NILP (tip_frame
) && XFRAME (tip_frame
) == f
1002 && ! FRAME_VISIBLE_P (f
))
1005 if (! FRAME_CR_SURFACE (f
))
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
);
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)
1029 FRAME_CR_SURFACE (f
) = cairo_image_surface_create
1030 (CAIRO_FORMAT_ARGB32
, width
, height
);
1034 #endif /* USE_CAIRO */
1037 /* Start update of window W. */
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
;
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
1056 if (FRAME_GARBAGED_P (f
))
1057 hlinfo
->mouse_face_window
= Qnil
;
1064 /* Draw a vertical window border from (x,y0) to (x,y1) */
1067 x_draw_vertical_window_border (struct window
*w
, int x
, int y0
, int y1
)
1069 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1072 face
= FACE_FROM_ID_OR_NULL (f
, VERTICAL_BORDER_FACE_ID
);
1074 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1078 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
, x
, y0
, 1, y1
- y0
);
1080 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
1081 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
1085 /* Draw a window divider from (x0,y0) to (x1,y1) */
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)
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)
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);
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
1153 x_update_window_end (struct window
*w
, bool cursor_on_p
,
1154 bool mouse_face_overwritten_p
)
1156 if (!w
->pseudo_window_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
);
1170 x_draw_vertical_border (w
);
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. */
1192 show_back_buffer (struct frame
*f
)
1195 if (FRAME_X_DOUBLE_BUFFERED_P (f
))
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);
1204 eassert (!"should have back-buffer only with XDBE");
1207 FRAME_X_NEED_BUFFER_FLIP (f
) = false;
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. */
1215 x_flip_and_flush (struct frame
*f
)
1218 if (FRAME_X_NEED_BUFFER_FLIP (f
))
1219 show_back_buffer (f
);
1224 /* End update of frame F. This function is installed as a hook in
1228 x_update_end (struct frame
*f
)
1230 /* Mouse highlight may be displayed again. */
1231 MOUSE_HL_INFO (f
)->mouse_face_defer
= false;
1234 if (FRAME_CR_SURFACE (f
))
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
);
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
,
1259 cr
= cairo_create (surface
);
1260 cairo_surface_destroy (surface
);
1263 cairo_set_source_surface (cr
, FRAME_CR_SURFACE (f
), 0, 0);
1272 XFlush (FRAME_X_DISPLAY (f
));
1277 /* This function is called from various places in xdisp.c
1278 whenever a complete update has been performed. */
1281 XTframe_up_to_date (struct frame
*f
)
1283 eassert (FRAME_X_P (f
));
1285 FRAME_MOUSE_UPDATE (f
);
1286 if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f
))
1287 show_back_buffer (f
);
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.
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
);
1315 int margin
= FRAME_TOP_MARGIN_HEIGHT (f
);
1317 struct face
*face
= FACE_FROM_ID_OR_NULL (f
, INTERNAL_BORDER_FACE_ID
);
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
));
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
);
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. */
1353 x_after_update_window_line (struct window
*w
, struct glyph_row
*desired_row
)
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. */
1371 if (windows_or_buffers_changed
1372 && desired_row
->full_width_p
1373 && (f
= XFRAME (w
->frame
),
1374 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1376 && (height
= desired_row
->visible_height
,
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
);
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
);
1396 x_clear_area (f
, 0, y
, width
, height
);
1397 x_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
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. */
1423 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
1425 XSetForeground (display
, face
->gc
, face
->background
);
1427 x_fill_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1430 XSetForeground (display
, face
->gc
, face
->foreground
);
1434 if (p
->which
&& p
->which
< max_fringe_bmp
)
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 */
1452 Drawable drawable
= FRAME_X_DRAWABLE (f
);
1454 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
1455 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
1459 bits
= (char *) (p
->bits
+ p
->dh
);
1461 bits
= (char *) p
->bits
+ p
->dh
;
1463 /* Draw the bitmap. I believe these small pixmaps can be cached
1465 pixmap
= XCreatePixmapFromBitmapData (display
, drawable
, bits
, p
->wd
, p
->h
,
1467 ? (p
->overlay_p
? face
->background
1468 : f
->output_data
.x
->cursor_pixel
)
1469 : face
->foreground
),
1470 face
->background
, depth
);
1474 clipmask
= XCreatePixmapFromBitmapData (display
,
1475 FRAME_DISPLAY_INFO (f
)->root_window
,
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
);
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 /***********************************************************************
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,
1528 static void x_draw_relief_rect (struct frame
*, int, int, int, int,
1529 int, bool, bool, bool, bool, bool,
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
*);
1536 static void x_check_font (struct frame
*, struct font
*);
1540 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
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
)
1550 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
1553 /* Cursor on non-default face: must merge. */
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
,
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. */
1595 x_set_mouse_face_gc (struct glyph_string
*s
)
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
);
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
);
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
;
1617 /* Otherwise construct scratch_cursor_gc with values from FACE
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
,
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. */
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
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;
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. */
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);
1705 x_set_clip_rectangles (s
->f
, s
->gc
, r
, 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
1715 x_set_glyph_string_clipping_exactly (struct glyph_string
*src
, struct glyph_string
*dst
)
1720 r
.width
= src
->width
;
1722 r
.height
= src
->height
;
1725 x_set_clip_rectangles (dst
->f
, dst
->gc
, &r
, 1);
1730 Compute left and right overhang of glyph string S. */
1733 x_compute_glyph_string_overhangs (struct glyph_string
*s
)
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
;
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
);
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;
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. */
1772 x_clear_glyph_string_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
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. */
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);
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
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. */
1830 x_draw_glyph_string_foreground (struct glyph_string
*s
)
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
);
1842 /* Draw characters of S as rectangles if S's font could not be
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,
1852 x
+= g
->pixel_width
;
1857 struct font
*font
= s
->font
;
1858 int boff
= font
->baseline_offset
;
1861 if (font
->vertical_centering
)
1862 boff
= VCENTER_BASELINE_OFFSET (font
, s
->f
) - boff
;
1864 y
= s
->ybase
- boff
;
1866 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1867 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, false);
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. */
1878 x_draw_composite_glyph_string_foreground (struct glyph_string
*s
)
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
);
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
)
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);
1923 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
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
);
1935 int xoff
, yoff
, wadjust
;
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);
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
,
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. */
1969 x_draw_glyphless_glyph_string_foreground (struct glyph_string
*s
)
1971 struct glyph
*glyph
= s
->first_glyph
;
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
);
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
)
1993 && CHAR_TABLE_P (Vglyphless_char_display
)
1994 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display
))
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 unsigned int ch
= glyph
->u
.glyphless
.ch
;
2009 eassume (ch
<= MAX_CHAR
);
2010 sprintf (buf
, "%0*X", ch
< 0x10000 ? 4 : 6, ch
);
2016 int upper_len
= (len
+ 1) / 2;
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
,
2029 s
->font
->driver
->draw (s
, upper_len
, len
,
2030 x
+ glyph
->slice
.glyphless
.lower_xoff
,
2031 s
->ybase
+ glyph
->slice
.glyphless
.lower_yoff
,
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
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
;
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
)
2072 && f
->output_data
.nothing
!= 1
2073 && FRAME_DISPLAY_INFO (f
) == dpyinfo
2074 && f
->output_data
.x
->widget
== widget
)
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. */
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
),
2105 {XtWidgetBaseOffset
, (XtPointer
) offsetof (WidgetRec
, core
.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. */
2134 cvt_string_to_pixel (Display
*dpy
, XrmValue
*args
, Cardinal
*nargs
,
2135 XrmValue
*from
, XrmValue
*to
,
2136 XtPointer
*closure_ret
)
2146 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
2147 "wrongParameters", "cvt_string_to_pixel",
2149 "Screen and colormap args required", NULL
, NULL
);
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
;
2176 Cardinal nparams
= 1;
2178 params
[0] = color_name
;
2179 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
2180 "badValue", "cvt_string_to_pixel",
2181 "XtToolkitError", "Invalid color '%s'",
2186 if (to
->addr
!= NULL
)
2188 if (to
->size
< sizeof (Pixel
))
2190 to
->size
= sizeof (Pixel
);
2194 *(Pixel
*) to
->addr
= pixel
;
2198 cvt_string_to_pixel_value
= pixel
;
2199 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
2202 to
->size
= sizeof (Pixel
);
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. */
2220 cvt_pixel_dtor (XtAppContext app
, XrmValuePtr to
, XtPointer closure
, XrmValuePtr args
,
2225 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
2227 "Screen and colormap arguments required",
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
);
2255 if (dpyinfo
->color_cells
== NULL
)
2257 Screen
*screen
= dpyinfo
->screen
;
2258 int ncolor_cells
= XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
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. */
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
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
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;
2329 if (dpyinfo
->color_cells
)
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
];
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. */
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
,
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
;
2388 if (XParseColor (dpy
, cmap
, color_name
, color
) == 0)
2389 /* No caching of negative results, currently. */
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
;
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
2407 x_alloc_nearest_color_1 (Display
*dpy
, Colormap cmap
, XColor
*color
)
2411 rc
= XAllocColor (dpy
, cmap
, color
) != 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. */
2419 int max_color_delta
= 255;
2420 int max_delta
= 3 * max_color_delta
;
2421 int nearest_delta
= max_delta
+ 1;
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
)
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;
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
);
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
2468 register_color (color
->pixel
);
2469 #endif /* DEBUG_X_COLORS */
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. */
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
,
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. */
2505 x_copy_color (struct frame
*f
, unsigned long pixel
)
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
)))
2516 color
.pixel
= pixel
;
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
);
2522 #ifdef DEBUG_X_COLORS
2523 register_color (pixel
);
2529 /* Brightness beyond which a color won't have its highlight brightness
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. */
2551 x_alloc_lighter_color (struct frame
*f
, Display
*display
, Colormap cmap
,
2552 unsigned long *pixel
, double factor
, int delta
)
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;
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
);
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);
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);
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. */
2628 x_setup_relief_color (struct frame
*f
, struct relief
*relief
, double factor
,
2629 int delta
, unsigned long default_pixel
)
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);
2652 /* Allocate new color. */
2653 xgcv
.foreground
= default_pixel
;
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
;
2663 relief
->gc
= XCreateGC (dpy
, FRAME_X_DRAWABLE (f
), mask
, &xgcv
);
2666 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
2670 /* Set up colors for the relief lines around glyph string S. */
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
2682 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2683 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
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
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
)
2721 GC top_left_gc
, bottom_right_gc
;
2726 top_left_gc
= f
->output_data
.x
->white_relief
.gc
;
2727 bottom_right_gc
= f
->output_data
.x
->black_relief
.gc
;
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);
2740 x_fill_rectangle (f
, top_left_gc
, left_x
, top_y
,
2741 width
, bottom_y
+ 1 - top_y
);
2743 corners
|= 1 << CORNER_TOP_LEFT
;
2745 corners
|= 1 << CORNER_BOTTOM_LEFT
;
2749 x_fill_rectangle (f
, bottom_right_gc
, right_x
+ 1 - width
, top_y
,
2750 width
, bottom_y
+ 1 - top_y
);
2752 corners
|= 1 << CORNER_TOP_RIGHT
;
2754 corners
|= 1 << CORNER_BOTTOM_RIGHT
;
2759 x_fill_rectangle (f
, top_left_gc
, left_x
, top_y
,
2760 right_x
+ 1 - left_x
, width
);
2762 x_fill_trapezoid_for_relief (f
, top_left_gc
, left_x
, top_y
,
2763 right_x
+ 1 - left_x
, width
, 1);
2768 x_fill_rectangle (f
, bottom_right_gc
, left_x
, bottom_y
+ 1 - width
,
2769 right_x
+ 1 - left_x
, width
);
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);
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,
2790 x_reset_clip_rectangles (f
, top_left_gc
);
2791 x_reset_clip_rectangles (f
, bottom_right_gc
);
2793 Display
*dpy
= FRAME_X_DISPLAY (f
);
2794 Drawable drawable
= FRAME_X_DRAWABLE (f
);
2799 gc
= f
->output_data
.x
->white_relief
.gc
;
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
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
);
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
);
2840 gc
= f
->output_data
.x
->black_relief
.gc
;
2842 gc
= f
->output_data
.x
->white_relief
.gc
;
2843 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2847 /* Outermost top line. */
2849 XDrawLine (dpy
, drawable
, gc
,
2850 left_x
+ left_p
, top_y
,
2851 right_x
+ !right_p
, top_y
);
2853 /* Outermost left line. */
2855 XDrawLine (dpy
, drawable
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
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
);
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
);
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. */
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
)
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);
2906 x_fill_rectangle (s
->f
, s
->gc
,
2907 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2911 x_fill_rectangle (s
->f
, s
->gc
,
2912 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2915 x_fill_rectangle (s
->f
, s
->gc
,
2916 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
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. */
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
2945 : s
->first_glyph
+ s
->nchars
- 1);
2947 width
= eabs (s
->face
->box_line_width
);
2948 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2950 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2952 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2954 bottom_y
= top_y
+ s
->height
- 1;
2956 left_p
= (s
->first_glyph
->left_box_line_p
2957 || (s
->hl
== DRAW_MOUSE_FACE
2959 || s
->prev
->hl
!= s
->hl
)));
2960 right_p
= (last_glyph
->right_box_line_p
2961 || (s
->hl
== DRAW_MOUSE_FACE
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
);
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
,
2980 /* Draw foreground of image glyph string S. */
2983 x_draw_image_foreground (struct glyph_string
*s
)
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
2993 x
+= eabs (s
->face
->box_line_width
);
2995 /* If there is a margin around the image, adjust x- and y-position
2997 if (s
->slice
.x
== 0)
2998 x
+= s
->img
->hmargin
;
2999 if (s
->slice
.y
== 0)
3000 y
+= s
->img
->vmargin
;
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
3011 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
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
);
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
);
3035 XRectangle clip_rect
, image_rect
, r
;
3037 get_glyph_string_clip_rect (s
, &clip_rect
);
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);
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. */
3074 x_draw_image_relief (struct glyph_string
*s
)
3077 bool raised_p
, top_p
, bot_p
, left_p
, right_p
;
3078 int extra_x
, extra_y
;
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
3088 x
+= eabs (s
->face
->box_line_width
);
3090 /* If there is a margin around the image, adjust x- and y-position
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
;
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. */
3147 x_draw_image_foreground_1 (struct glyph_string
*s
, Pixmap pixmap
)
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
3157 x
+= eabs (s
->face
->box_line_width
);
3159 /* If there is a margin around the image, adjust x- and y-position
3161 if (s
->slice
.x
== 0)
3162 x
+= s
->img
->hmargin
;
3163 if (s
->slice
.y
== 0)
3164 y
+= s
->img
->vmargin
;
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
3175 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
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
);
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);
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. */
3222 x_draw_glyph_string_bg_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
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
);
3232 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3236 /* Draw image glyph string S.
3239 s->x +-------------------------
3242 | +-------------------------
3245 | | +-------------------
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);
3256 Pixmap pixmap
= None
;
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
3267 s
->stippled_p
= s
->face
->stipple
!= 0;
3268 if (height
> s
->slice
.height
3272 || s
->img
->pixmap
== 0
3273 || s
->width
!= s
->background_width
)
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
,
3288 /* Don't clip in the following because we're working on the
3290 XSetClipMask (s
->display
, s
->gc
, None
);
3292 /* Fill the pixmap with the background color/stipple. */
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);
3306 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
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
);
3318 int width
= s
->background_width
;
3320 if (s
->first_glyph
->left_box_line_p
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. */
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
,
3349 cairo_rectangle (cr
, x
, y
, width
, height
);
3351 x_end_cr_clip (s
->f
);
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
);
3364 x_draw_image_foreground (s
);
3366 /* If we must draw a relief around the image, do it. */
3368 || s
->hl
== DRAW_IMAGE_RAISED
3369 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3370 x_draw_image_relief (s
);
3374 /* Draw stretch glyph string S. */
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
;
3389 if (!s
->row
->reversed_p
)
3391 int left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3395 background_width
-= left_x
- x
;
3401 /* In R2L rows, draw the cursor on the right edge of the
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
)
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
)
3420 int w
= background_width
- width
, h
= s
->height
;
3424 if (!s
->row
->reversed_p
)
3428 if (s
->row
->mouse_face_p
3429 && cursor_in_mouse_face_p (s
->w
))
3431 x_set_mouse_face_gc (s
);
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
);
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
;
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.
3485 wave_height = 3 | * * * *
3490 x_draw_underwave (struct glyph_string
*s
)
3492 int wave_height
= 3, wave_length
= 2;
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
;
3499 XRectangle wave_clip
, string_clip
, final_clip
;
3502 dy
= wave_height
- 1;
3504 y0
= s
->ybase
- wave_height
+ 3;
3508 /* Find and set clipping rectangle */
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
))
3519 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &final_clip
, 1, Unsorted
);
3521 /* Draw the waves */
3523 x1
= x0
- (x0
% dx
);
3525 odd
= (x1
/ dx
) & 1;
3533 if (INT_MAX
- dx
< xmax
)
3538 XDrawLine (s
->display
, FRAME_X_DRAWABLE (s
->f
), s
->gc
, x1
, y1
, x2
, y2
);
3540 x2
+= dx
, y2
= y0
+ odd
*dy
;
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. */
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
)
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
);
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. */
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
);
3606 x_set_glyph_string_clipping (s
);
3608 switch (s
->first_glyph
->type
)
3611 x_draw_image_glyph_string (s
);
3615 x_draw_xwidget_glyph_string (s
);
3619 x_draw_stretch_glyph_string (s
);
3623 if (s
->for_overlaps
)
3624 s
->background_filled_p
= true;
3626 x_draw_glyph_string_background (s
, false);
3627 x_draw_glyph_string_foreground (s
);
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;
3635 x_draw_glyph_string_background (s
, true);
3636 x_draw_composite_glyph_string_foreground (s
);
3639 case GLYPHLESS_GLYPH
:
3640 if (s
->for_overlaps
)
3641 s
->background_filled_p
= true;
3643 x_draw_glyph_string_background (s
, true);
3644 x_draw_glyphless_glyph_string_foreground (s
);
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
);
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
;
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
;
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
;
3690 if (x_underline_at_descent_line
)
3691 position
= (s
->height
- thickness
) - (s
->ybase
- s
->y
);
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
;
3706 position
= (font
->descent
+ 1) / 2;
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
);
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
,
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
,
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
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
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
,
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
,
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
);
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
;
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
);
3805 x_draw_composite_glyph_string_foreground (prev
);
3806 x_reset_clip_rectangles (prev
->f
, prev
->gc
);
3808 prev
->num_clips
= 0;
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
;
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
);
3830 x_draw_composite_glyph_string_foreground (next
);
3831 x_reset_clip_rectangles (next
->f
, next
->gc
);
3833 next
->num_clips
= 0;
3834 next
->clip_head
= s
->next
;
3839 /* Reset clipping. */
3840 x_reset_clip_rectangles (s
->f
, s
->gc
);
3844 /* Shift display to make room for inserted glyphs. */
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
,
3858 /* Delete N glyphs at the nominal cursor position. Not implemented
3862 x_delete_glyphs (struct frame
*f
, register int n
)
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
);
3880 x_clear_area (struct frame
*f
, int x
, int y
, int width
, int height
)
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
);
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
);
3899 x_clear_area1 (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3900 x
, y
, width
, height
, False
);
3905 /* Clear an entire frame. */
3908 x_clear_frame (struct frame
*f
)
3910 /* Clearing the frame will erase any cursor, so mark them all as no
3912 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3916 font_drop_xrender_surfaces (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
));
3928 /* RIF: Show hourglass cursor on frame F. */
3931 x_show_hourglass (struct frame
*f
)
3933 Display
*dpy
= FRAME_X_DISPLAY (f
);
3937 struct x_output
*x
= FRAME_X_OUTPUT (f
);
3938 #ifdef USE_X_TOOLKIT
3941 if (FRAME_OUTER_WINDOW (f
))
3944 x
->hourglass_p
= true;
3946 if (!x
->hourglass_window
)
3948 unsigned long mask
= CWCursor
;
3949 XSetWindowAttributes attrs
;
3951 Window parent
= FRAME_X_WINDOW (f
);
3953 Window parent
= FRAME_OUTER_WINDOW (f
);
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
);
3968 /* RIF: Cancel hourglass cursor on frame F. */
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. */
3989 XTflash (struct frame
*f
)
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
));
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) \
4004 cairo_rectangle (cr, x, y, w, h); \
4008 #else /* ! HAVE_GTK3 */
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 */
4022 /* Create a GC that will use the GXxor function to flip foreground
4023 pixels into background pixels. */
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
);
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
,
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
,
4055 (height
- flash_height
4056 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4057 width
, flash_height
);
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
));
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
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)
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
,
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
,
4101 (height
- flash_height
4102 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4103 width
, flash_height
);
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
));
4115 g_object_unref (G_OBJECT (gc
));
4117 #undef XFillRectangle
4119 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
4130 XTtoggle_invisible_pointer (struct frame
*f
, bool invisible
)
4133 FRAME_DISPLAY_INFO (f
)->toggle_visible_pointer (f
, invisible
);
4138 /* Make audible bell. */
4141 XTring_bell (struct frame
*f
)
4143 if (FRAME_X_DISPLAY (f
))
4151 XkbBell (FRAME_X_DISPLAY (f
), None
, 0, None
);
4153 XBell (FRAME_X_DISPLAY (f
), 0);
4155 XFlush (FRAME_X_DISPLAY (f
));
4161 /***********************************************************************
4163 ***********************************************************************/
4165 /* Perform an insert-lines or delete-lines operation, inserting N
4166 lines or deleting -N lines at vertical position VPOS. */
4169 x_ins_del_lines (struct frame
*f
, int vpos
, int n
)
4175 /* Scroll part of the display as described by RUN. */
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
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
;
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
;
4199 height
= run
->height
;
4203 /* Scrolling down. Make sure we don't copy over the mode line.
4205 if (to_y
+ run
->height
> bottom_y
)
4206 height
= bottom_y
- to_y
;
4208 height
= run
->height
;
4213 /* Cursor off. Will be switched on again in x_update_window_end. */
4217 SET_FRAME_GARBAGED (f
);
4219 XCopyArea (FRAME_X_DISPLAY (f
),
4220 FRAME_X_DRAWABLE (f
), FRAME_X_DRAWABLE (f
),
4221 f
->output_data
.x
->normal_gc
,
4232 /***********************************************************************
4234 ***********************************************************************/
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. */
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 ();
4254 x_update_cursor (f
, true);
4255 x_set_frame_alpha (f
);
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. */
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 ();
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. */
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
;
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. */
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
)))
4328 bufp
->kind
= FOCUS_IN_EVENT
;
4329 XSETFRAME (bufp
->frame_or_window
, frame
);
4332 frame
->output_data
.x
->focus_state
|= state
;
4335 if (FRAME_XIC (frame
))
4336 XSetICFocus (FRAME_XIC (frame
));
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
);
4353 if (FRAME_XIC (frame
))
4354 XUnsetICFocus (FRAME_XIC (frame
));
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
;
4373 FOR_EACH_FRAME (tail
, frame
)
4376 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4378 if (f
->output_data
.x
->hourglass_window
== wdesc
)
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
)
4388 #else /* not USE_X_TOOLKIT */
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
)
4397 #endif /* USE_GTK */
4398 if (FRAME_X_WINDOW (f
) == wdesc
4399 || f
->output_data
.x
->icon_desc
== wdesc
)
4401 #endif /* not USE_X_TOOLKIT */
4406 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4408 /* Like x_window_to_frame but also compares the window with the widget's
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
;
4421 FOR_EACH_FRAME (tail
, 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
)
4435 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
4437 && gtk_widget_get_toplevel (gwdesc
) == x
->widget
)
4440 if (wdesc
== XtWindow (x
->widget
)
4441 || wdesc
== XtWindow (x
->column_widget
)
4442 || wdesc
== XtWindow (x
->edit_widget
))
4444 /* Match if the window is this frame's menubar. */
4445 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
4449 else if (FRAME_X_WINDOW (f
) == wdesc
)
4450 /* A tooltip frame. */
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
;
4472 FOR_EACH_FRAME (tail
, frame
)
4475 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4477 x
= f
->output_data
.x
;
4479 if (x
->menubar_widget
&& xg_event_is_for_menubar (f
, event
))
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
))
4491 /* Return the frame whose principal (outermost) window is WDESC.
4492 If WDESC is some other (smaller) window, we return 0. */
4495 x_top_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
4497 Lisp_Object tail
, frame
;
4504 FOR_EACH_FRAME (tail
, frame
)
4507 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4509 x
= f
->output_data
.x
;
4513 /* This frame matches if the window is its topmost widget. */
4515 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
4516 if (gwdesc
== x
->widget
)
4519 if (wdesc
== XtWindow (x
->widget
))
4523 else if (FRAME_X_WINDOW (f
) == wdesc
)
4524 /* Tooltip frame. */
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. */
4543 x_detect_focus_change (struct x_display_info
*dpyinfo
, struct frame
*frame
,
4544 const XEvent
*event
, struct input_event
*bufp
)
4549 switch (event
->type
)
4554 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
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
),
4563 dpyinfo
, frame
, bufp
);
4569 x_focus_changed (event
->type
,
4570 (event
->xfocus
.detail
== NotifyPointer
?
4571 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
4572 dpyinfo
, frame
, bufp
);
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
);
4587 #if !defined USE_X_TOOLKIT && !defined USE_GTK
4588 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4591 x_mouse_leave (struct x_display_info
*dpyinfo
)
4593 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
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. */
4606 XTframe_rehighlight (struct frame
*frame
)
4608 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame
));
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
;
4629 dpyinfo
->x_highlight_frame
= 0;
4631 if (dpyinfo
->x_highlight_frame
!= 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. */
4646 x_find_modifier_meanings (struct x_display_info
*dpyinfo
)
4648 int min_code
, max_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,
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. */
4683 /* Are any of this keycode's keysyms a meta key? */
4687 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
4689 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
4695 found_alt_or_meta
= true;
4696 dpyinfo
->meta_mod_mask
|= (1 << row
);
4701 found_alt_or_meta
= true;
4702 dpyinfo
->alt_mod_mask
|= (1 << row
);
4707 if (!found_alt_or_meta
)
4708 dpyinfo
->hyper_mod_mask
|= (1 << row
);
4709 code_col
= syms_per_code
;
4710 col
= mods
->max_keypermod
;
4715 if (!found_alt_or_meta
)
4716 dpyinfo
->super_mod_mask
|= (1 << row
);
4717 code_col
= syms_per_code
;
4718 col
= mods
->max_keypermod
;
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
;
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
;
4750 XFreeModifiermap (mods
);
4753 /* Convert between the modifier bits X uses and the modifier bits
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
;
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));
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
;
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. */
4819 x_get_keysym_name (int keysym
)
4824 value
= XKeysymToString (keysym
);
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
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
4856 construct_mouse_click (struct input_event
*result
,
4857 const XButtonEvent
*event
,
4860 /* Make the event type NO_EVENT; we'll change that when we decide
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
),
4867 | (event
->type
== ButtonRelease
4871 XSETINT (result
->x
, event
->x
);
4872 XSETINT (result
->y
, event
->y
);
4873 XSETFRAME (result
->frame_or_window
, f
);
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. */
4887 note_mouse_movement (struct frame
*frame
, const XMotionEvent
*event
)
4890 struct x_display_info
*dpyinfo
;
4892 if (!FRAME_X_OUTPUT (frame
))
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
;
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
;
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
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
4950 XTmouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
4951 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
4955 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
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
);
4966 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, timestamp
);
4973 Window dummy_window
;
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. */
4993 /* Trash which we can't trust if the pointer is on
4994 a different screen. */
4997 /* The position on that root window. */
5000 /* More trash we can't trust. */
5003 /* Modifier keys and pointer buttons, about which
5005 (unsigned int *) &dummy
);
5007 /* Now we have a position on the root; find the innermost window
5008 containing the pointer. */
5012 Window first_win
= 0;
5015 int parent_x
= 0, parent_y
= 0;
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
),
5035 FRAME_X_WINDOW (dpyinfo
->last_mouse_frame
),
5037 /* From-position, to-position. */
5038 root_x
, root_y
, &win_x
, &win_y
,
5042 f1
= dpyinfo
->last_mouse_frame
;
5048 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
5050 /* From-window, to-window. */
5053 /* From-position, to-position. */
5054 root_x
, root_y
, &win_x
, &win_y
,
5059 if (child
== None
|| child
== win
)
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
))
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
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.) */
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
);
5107 /* Is win one of our frames? */
5108 f1
= x_any_window_to_frame (dpyinfo
, win
);
5111 #ifdef USE_X_TOOLKIT
5112 /* If we end up with the menu bar window, say it's not
5115 && f1
->output_data
.x
->menubar_widget
5116 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
5118 #endif /* USE_X_TOOLKIT */
5121 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
5124 x_uncatch_errors_after_check ();
5126 /* If not, is it one of our scroll bars? */
5129 struct scroll_bar
*bar
;
5131 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
, 2);
5135 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5141 if (f1
== 0 && insist
> 0)
5142 f1
= SELECTED_FRAME ();
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
;
5162 XSETINT (*x
, win_x
);
5163 XSETINT (*y
, win_y
);
5164 *timestamp
= dpyinfo
->last_mouse_movement_time
;
5174 /***********************************************************************
5176 ***********************************************************************/
5178 /* Scroll bar support. */
5180 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
5182 This can be called in GC, so we have to make sure to strip off mark
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
)))
5201 /* Scan this frame's scroll bar list for a scroll bar with the
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
,
5210 bar
= XSCROLL_BAR (bar
)->next
)
5211 if (XSCROLL_BAR (bar
)->x_window
== window_id
5212 && FRAME_X_DISPLAY (XFRAME (frame
)) == display
5214 || (type
== 1 && XSCROLL_BAR (bar
)->horizontal
)
5215 || (type
== 0 && !XSCROLL_BAR (bar
)->horizontal
)))
5216 return XSCROLL_BAR (bar
);
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. */
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
))
5244 #endif /* USE_LUCID */
5247 /************************************************************************
5249 ************************************************************************/
5251 #ifdef USE_TOOLKIT_SCROLL_BARS
5253 static void x_send_scroll_bar_event (Lisp_Object
, enum scroll_bar_part
,
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. */
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. */
5284 xt_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
5285 XEvent
*event
, String
*params
, Cardinal
*num_params
)
5288 const char *end_action
;
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 */
5299 && strcmp (action_name
, end_action
) == 0
5300 && WINDOWP (window_being_scrolled
))
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)
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
;
5320 /* Xt timeouts no longer needed. */
5321 toolkit_scroll_bar_interaction
= false;
5327 xt_horizontal_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
5328 XEvent
*event
, String
*params
, Cardinal
*num_params
)
5331 const char *end_action
;
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 */
5342 && strcmp (action_name
, end_action
) == 0
5343 && WINDOWP (window_being_scrolled
))
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)
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
;
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. */
5377 x_send_scroll_bar_event (Lisp_Object window
, enum scroll_bar_part part
,
5378 int portion
, int whole
, bool horizontal
)
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;
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
);
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 ();
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
);
5424 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
5428 x_scroll_bar_to_input_event (const XEvent
*event
,
5429 struct input_event
*ievent
)
5431 const XClientMessageEvent
*ev
= &event
->xclient
;
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
;
5447 ievent
->timestamp
= CurrentTime
;
5450 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
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. */
5463 x_horizontal_scroll_bar_to_input_event (const XEvent
*event
,
5464 struct input_event
*ievent
)
5466 const XClientMessageEvent
*ev
= &event
->xclient
;
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
;
5482 ievent
->timestamp
= CurrentTime
;
5485 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
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;
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. */
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;
5516 case XmCR_DECREMENT
:
5518 part
= horizontal
? scroll_bar_left_arrow
: scroll_bar_up_arrow
;
5521 case XmCR_INCREMENT
:
5523 part
= horizontal
? scroll_bar_right_arrow
: scroll_bar_down_arrow
;
5526 case XmCR_PAGE_DECREMENT
:
5528 part
= horizontal
? scroll_bar_before_handle
: scroll_bar_above_handle
;
5531 case XmCR_PAGE_INCREMENT
:
5533 part
= horizontal
? scroll_bar_after_handle
: scroll_bar_below_handle
;
5538 part
= horizontal
? scroll_bar_to_leftmost
: scroll_bar_to_top
;
5541 case XmCR_TO_BOTTOM
:
5543 part
= horizontal
? scroll_bar_to_rightmost
: scroll_bar_to_bottom
;
5551 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
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
;
5563 whole
= XM_SB_MAX
- slider_size
;
5564 portion
= min (cs
->value
, whole
);
5565 part
= scroll_bar_handle
;
5568 bar
->dragging
= cs
->value
;
5572 case XmCR_VALUE_CHANGED
:
5576 if (part
!= scroll_bar_nowhere
)
5578 window_being_scrolled
= bar
->window
;
5579 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
,
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. */
5590 xg_scroll_callback (GtkRange
*range
,
5591 GtkScrollType scroll
,
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;
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
;
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
;
5628 case GTK_SCROLL_STEP_BACKWARD
:
5629 part
= (bar
->horizontal
5630 ? scroll_bar_left_arrow
: scroll_bar_up_arrow
);
5633 case GTK_SCROLL_STEP_FORWARD
:
5634 part
= (bar
->horizontal
5635 ? scroll_bar_right_arrow
: scroll_bar_down_arrow
);
5638 case GTK_SCROLL_PAGE_BACKWARD
:
5639 part
= (bar
->horizontal
5640 ? scroll_bar_before_handle
: scroll_bar_above_handle
);
5643 case GTK_SCROLL_PAGE_FORWARD
:
5644 part
= (bar
->horizontal
5645 ? scroll_bar_after_handle
: scroll_bar_below_handle
);
5652 if (part
!= scroll_bar_nowhere
)
5654 window_being_scrolled
= bar
->window
;
5655 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
,
5662 /* Callback for button release. Sets dragging to -1 when dragging is done. */
5665 xg_end_scroll_callback (GtkWidget
*widget
,
5666 GdkEventButton
*event
,
5669 struct scroll_bar
*bar
= user_data
;
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
;
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
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
;
5696 int whole
, portion
, height
, width
;
5697 enum scroll_bar_part part
;
5698 bool horizontal
= bar
->horizontal
;
5703 /* Get the size of the thumb, a value between 0 and 1. */
5705 XtVaGetValues (widget
, XtNshown
, &shown
, XtNwidth
, &width
, NULL
);
5710 whole
= bar
->whole
- (shown
* bar
->whole
);
5711 portion
= min (top
* bar
->whole
, whole
);
5719 part
= scroll_bar_horizontal_handle
;
5723 /* Get the size of the thumb, a value between 0 and 1. */
5725 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
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
5737 part
= scroll_bar_down_arrow
;
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. */
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. */
5770 XtVaGetValues (widget
, XtNwidth
, &width
, NULL
);
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
;
5781 part
= scroll_bar_move_ratio
;
5783 window_being_scrolled
= bar
->window
;
5785 bar
->last_seen_part
= part
;
5786 x_send_scroll_bar_event (bar
->window
, part
, position
, width
,
5792 /* Get the height of the scroll bar. */
5794 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
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
;
5805 part
= scroll_bar_move_ratio
;
5807 window_being_scrolled
= bar
->window
;
5809 bar
->last_seen_part
= part
;
5810 x_send_scroll_bar_event (bar
->window
, part
, position
, height
,
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. */
5825 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5827 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
5830 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
5831 G_CALLBACK (xg_end_scroll_callback
),
5837 x_create_horizontal_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5839 const char *scroll_bar_name
= SCROLL_BAR_HORIZONTAL_NAME
;
5842 xg_create_horizontal_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
5843 G_CALLBACK (xg_end_scroll_callback
),
5848 #else /* not USE_GTK */
5851 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5857 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
5858 unsigned long pixel
;
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
;
5875 XtSetArg (av
[ac
], XmNforeground
, pixel
);
5879 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5882 XtSetArg (av
[ac
], XmNbackground
, pixel
);
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
,
5892 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
5894 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
5896 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
5898 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
5900 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
5902 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
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
;
5927 XtSetArg (av
[ac
], XtNforeground
, pixel
);
5931 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5934 XtSetArg (av
[ac
], XtNbackground
, pixel
);
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
;
5946 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
5947 FRAME_X_COLORMAP (f
),
5948 &pixel
, 1.2, 0x8000))
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
;
5958 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
5959 FRAME_X_COLORMAP (f
),
5960 &pixel
, 0.6, 0x4000))
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
5975 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
5976 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
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
5986 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
5989 /* Specify the colors. */
5990 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
5993 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
5996 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
5999 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
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
,
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
,
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
;
6044 bar
->horizontal
= false;
6050 x_create_horizontal_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
6056 const char *scroll_bar_name
= SCROLL_BAR_HORIZONTAL_NAME
;
6057 unsigned long pixel
;
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
;
6074 XtSetArg (av
[ac
], XmNforeground
, pixel
);
6078 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
6081 XtSetArg (av
[ac
], XmNbackground
, pixel
);
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
,
6091 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
6093 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
6095 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
6097 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
6099 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
6101 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
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
;
6126 XtSetArg (av
[ac
], XtNforeground
, pixel
);
6130 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
6133 XtSetArg (av
[ac
], XtNbackground
, pixel
);
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
;
6145 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
6146 FRAME_X_COLORMAP (f
),
6147 &pixel
, 1.2, 0x8000))
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
;
6157 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
6158 FRAME_X_COLORMAP (f
),
6159 &pixel
, 0.6, 0x4000))
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
6174 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
6175 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
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
6185 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
6188 /* Specify the colors. */
6189 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
6192 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
6195 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
6198 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
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
,
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
,
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
;
6244 bar
->horizontal
= true;
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. */
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
);
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 */
6269 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
6272 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6273 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
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. */
6303 top
= (float) position
/ whole
;
6304 shown
= (float) portion
/ whole
;
6307 if (bar
->dragging
== -1)
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
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 */
6328 top
= (float) position
/ whole
;
6329 shown
= (float) portion
/ whole
;
6333 float old_top
, old_shown
;
6335 XtVaGetValues (widget
,
6336 XtNtopOfThumb
, &old_top
,
6337 XtNshown
, &old_shown
,
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
));
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
);
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
);
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
);
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 */
6381 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
6384 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6385 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
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 */
6406 top
= (float) position
/ whole
;
6407 shown
= (float) portion
/ whole
;
6411 float old_top
, old_shown
;
6413 XtVaGetValues (widget
,
6414 XtNtopOfThumb
, &old_top
,
6415 XtNshown
, &old_shown
,
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
));
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
);
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
);
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
);
6443 if (top
!= old_top
|| shown
!= old_shown
)
6445 if (bar
->dragging
== -1)
6446 XawScrollbarSetThumb (widget
, top
, shown
);
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
);
6458 #endif /* !USE_MOTIF */
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
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
);
6488 #ifdef USE_TOOLKIT_SCROLL_BARS
6490 x_create_horizontal_toolkit_scroll_bar (f
, bar
);
6492 x_create_toolkit_scroll_bar (f
, bar
);
6493 #else /* not USE_TOOLKIT_SCROLL_BARS */
6495 XSetWindowAttributes a
;
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
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. */
6526 bar
->x_window
= window
;
6528 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6530 XSETWINDOW (bar
->window
, w
);
6534 bar
->height
= height
;
6538 bar
->horizontal
= horizontal
;
6539 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
6540 bar
->last_seen_part
= scroll_bar_nowhere
;
6543 /* Add bar to its frame's list of scroll bars. */
6544 bar
->next
= FRAME_SCROLL_BARS (f
);
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
6556 xg_update_horizontal_scrollbar_pos (f
, bar
->x_window
, top
,
6557 left
, width
, max (height
, 1));
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 */
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
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. */
6596 x_scroll_bar_set_handle (struct scroll_bar
*bar
, int start
, int end
,
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. */
6606 && start
== bar
->start
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
;
6624 else if (start
> top_range
)
6626 end
= start
+ length
;
6630 else if (end
> top_range
&& ! dragging
)
6634 /* Store the adjusted setting in the scroll bar. */
6638 /* Clip the end position, just for display. */
6639 if (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
);
6684 #endif /* !USE_TOOLKIT_SCROLL_BARS */
6686 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6690 x_scroll_bar_remove (struct scroll_bar
*bar
)
6692 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6695 #ifdef USE_TOOLKIT_SCROLL_BARS
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 */
6702 XDestroyWindow (FRAME_X_DISPLAY (f
), bar
->x_window
);
6705 /* Dissociate this scroll bar from its window. */
6706 if (bar
->horizontal
)
6707 wset_horizontal_scroll_bar (XWINDOW (bar
->window
), Qnil
);
6709 wset_vertical_scroll_bar (XWINDOW (bar
->window
), Qnil
);
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,
6721 XTset_vertical_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
6723 struct frame
*f
= XFRAME (w
->frame
);
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
);
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)
6742 x_clear_area (f
, left
, top
, width
, height
);
6746 bar
= x_scroll_bar_create (w
, top
, left
, width
, max (height
, 1), false);
6750 /* It may just need to be moved and resized. */
6751 unsigned int mask
= 0;
6753 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
6757 if (left
!= bar
->left
)
6759 if (top
!= bar
->top
)
6761 if (width
!= bar
->width
)
6763 if (height
!= bar
->height
)
6766 #ifdef USE_TOOLKIT_SCROLL_BARS
6768 /* Move/size the scroll bar widget. */
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
);
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. */
6794 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
6798 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6800 /* Remember new settings. */
6804 bar
->height
= height
;
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
6814 if (bar
->dragging
== -1)
6816 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
6819 x_scroll_bar_set_handle (bar
, 0, top_range
, false);
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
);
6835 XTset_horizontal_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
6837 struct frame
*f
= XFRAME (w
->frame
);
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);
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)
6858 /* Clear also part between window_width and
6859 WINDOW_PIXEL_WIDTH. */
6860 x_clear_area (f
, left
, top
, pixel_width
, height
);
6864 bar
= x_scroll_bar_create (w
, top
, left
, width
, height
, true);
6868 /* It may just need to be moved and resized. */
6869 unsigned int mask
= 0;
6871 bar
= XSCROLL_BAR (w
->horizontal_scroll_bar
);
6875 if (left
!= bar
->left
)
6877 if (top
!= bar
->top
)
6879 if (width
!= bar
->width
)
6881 if (height
!= bar
->height
)
6884 #ifdef USE_TOOLKIT_SCROLL_BARS
6885 /* Move/size the scroll bar widget. */
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)
6892 WINDOW_LEFT_EDGE_X (w
), top
,
6893 pixel_width
- WINDOW_RIGHT_DIVIDER_WIDTH (w
), height
);
6895 xg_update_horizontal_scrollbar_pos (f
, bar
->x_window
, top
, left
,
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
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. */
6924 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
6928 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6930 /* Remember new settings. */
6934 bar
->height
= height
;
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
6944 if (bar
->dragging
== -1)
6946 int left_range
= HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f
, width
);
6949 x_scroll_bar_set_handle (bar
, 0, left_range
, false);
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. */
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. */
7003 XTredeem_scroll_bar (struct window
*w
)
7005 struct scroll_bar
*bar
;
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
))
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
7022 if (EQ (FRAME_SCROLL_BARS (f
), w
->vertical_scroll_bar
))
7023 /* It's not condemned. Everything's fine. */
7025 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
7026 w
->vertical_scroll_bar
))
7027 fset_condemned_scroll_bars (f
, bar
->next
);
7029 /* If its prev pointer is nil, it must be at the front of
7030 one or the other! */
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
);
7041 XSETVECTOR (barobj
, bar
);
7042 fset_scroll_bars (f
, barobj
);
7043 if (! NILP (bar
->next
))
7044 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
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
7057 if (EQ (FRAME_SCROLL_BARS (f
), w
->horizontal_scroll_bar
))
7058 /* It's not condemned. Everything's fine. */
7060 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
7061 w
->horizontal_scroll_bar
))
7062 fset_condemned_scroll_bars (f
, bar
->next
);
7064 /* If its prev pointer is nil, it must be at the front of
7065 one or the other! */
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
);
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'. */
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
);
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
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
;
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
));
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
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
))
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
7176 emacs_event
->frame_or_window
= bar
->window
;
7177 emacs_event
->arg
= Qnil
;
7178 emacs_event
->timestamp
= event
->xbutton
.time
;
7179 if (bar
->horizontal
)
7182 = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f
, bar
->width
);
7183 int x
= event
->xbutton
.x
- HORIZONTAL_SCROLL_BAR_LEFT_BORDER
;
7186 if (x
> left_range
) x
= left_range
;
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
;
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);
7207 XSETINT (emacs_event
->x
, left_range
);
7208 XSETINT (emacs_event
->y
, x
);
7213 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
7214 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
7217 if (y
> top_range
) y
= top_range
;
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
;
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);
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
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. */
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
)));
7291 Window dummy_window
;
7293 unsigned int dummy_mask
;
7297 /* Get the mouse's position relative to the scroll bar window, and
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. */
7308 /* Mouse buttons and modifier keys. */
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
;
7320 if (win_y
> top_range
)
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
;
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
;
7347 /* Return information to the user about the current position of the mouse
7348 on the scroll bar. */
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
)));
7360 Window dummy_window
;
7362 unsigned int dummy_mask
;
7366 /* Get the mouse's position relative to the scroll bar window, and
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. */
7377 /* Mouse buttons and modifier keys. */
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
;
7389 if (win_x
> left_range
)
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
;
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
;
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
7422 x_scroll_bar_clear (struct frame
*f
)
7424 #ifndef USE_TOOLKIT_SCROLL_BARS
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
,
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)) \
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
;
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
7483 Returns zero if event is wasn't filtered. */
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
7494 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
7495 event
->xclient
.window
);
7497 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
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
;
7515 if (current_count
>= 0)
7517 struct x_display_info
*dpyinfo
;
7519 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
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
)
7527 && x_filter_event (dpyinfo
, xev
))
7530 return GDK_FILTER_REMOVE
;
7535 current_finish
= X_EVENT_NORMAL
;
7538 += handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
7542 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
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
);
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
);
7569 case FULLSCREEN_WIDTH
:
7572 case FULLSCREEN_HEIGHT
:
7575 case FULLSCREEN_BOTH
:
7578 case FULLSCREEN_MAXIMIZED
:
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. */
7593 flush_dirty_back_buffers (void)
7596 Lisp_Object tail
, frame
;
7597 FOR_EACH_FRAME (tail
, frame
)
7599 struct frame
*f
= XFRAME (frame
);
7600 if (FRAME_LIVE_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
);
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. */
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
;
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
;
7642 *finish
= X_EVENT_NORMAL
;
7644 EVENT_INIT (inev
.ie
);
7645 inev
.ie
.kind
= NO_EVENT
;
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
)
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. */
7667 /* Not quite sure this is needed -pd */
7668 if (f
&& FRAME_XIC (f
))
7669 XSetICFocus (FRAME_XIC (f
));
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
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
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. */
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. */
7694 XSetInputFocus (d
, event
->xclient
.window
,
7695 /* The ICCCM says this is
7696 the only valid choice. */
7698 event
->xclient
.data
.l
[1]);
7699 x_uncatch_errors ();
7701 /* Not certain about handling scroll bars here */
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. */
7717 if (! x_session_have_connection ())
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
);
7729 XSetCommand (FRAME_X_DISPLAY (f
),
7730 event
->xclient
.window
,
7736 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_delete_window
)
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
);
7750 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_configure_denied
)
7753 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_window_moved
)
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];
7763 f
->left_pos
= new_x
;
7769 #ifdef X_TOOLKIT_EDITRES
7770 if (event
->xclient
.message_type
== dpyinfo
->Xatom_editres
)
7774 _XEditResCheckMessages (f
->output_data
.x
->widget
,
7775 NULL
, (XEvent
*) event
, NULL
);
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
);
7791 x_kill_gs_process (pixmap
, f
);
7792 expose_frame (f
, 0, 0, 0, 0);
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
;
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
;
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
;
7824 xft_settings_event (dpyinfo
, event
);
7829 if (x_handle_dnd_message (f
, &event
->xclient
, dpyinfo
, &inev
.ie
))
7830 *finish
= X_EVENT_DROP
;
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
))
7839 #endif /* not USE_X_TOOLKIT */
7840 x_handle_selection_notify (&event
->xselection
);
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
))
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
;
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
))
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
;
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
);
7908 case ReparentNotify
:
7909 f
= x_top_window_to_frame (dpyinfo
, event
->xreparent
.window
);
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
);
7919 unsigned int dummy_uint
;
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
);
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
);
7937 f
= x_window_to_frame (dpyinfo
, event
->xexpose
.window
);
7940 if (!FRAME_VISIBLE_P (f
))
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
);
7951 else if (FRAME_GARBAGED_P (f
))
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. */
7961 FRAME_X_DISPLAY (f
),
7963 event
->xexpose
.x
, event
->xexpose
.y
,
7964 event
->xexpose
.width
, event
->xexpose
.height
,
7966 x_clear_under_internal_border (f
);
7971 if (!FRAME_GARBAGED_P (f
))
7974 /* This seems to be needed for GTK 2.6 and later, see
7975 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
7977 event
->xexpose
.x
, event
->xexpose
.y
,
7978 event
->xexpose
.width
, event
->xexpose
.height
);
7980 expose_frame (f
, event
->xexpose
.x
, event
->xexpose
.y
,
7981 event
->xexpose
.width
, event
->xexpose
.height
);
7983 x_clear_under_internal_border (f
);
7987 if (!FRAME_GARBAGED_P (f
))
7988 show_back_buffer (f
);
7992 #ifndef USE_TOOLKIT_SCROLL_BARS
7993 struct scroll_bar
*bar
;
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
);
8002 xlwmenu_redisplay (widget
);
8004 #endif /* USE_LUCID */
8006 #ifdef USE_TOOLKIT_SCROLL_BARS
8007 /* Dispatch event to the widget. */
8009 #else /* not USE_TOOLKIT_SCROLL_BARS */
8010 bar
= x_window_to_scroll_bar (event
->xexpose
.display
,
8011 event
->xexpose
.window
, 2);
8014 x_scroll_bar_expose (bar
, event
);
8015 #ifdef USE_X_TOOLKIT
8018 #endif /* USE_X_TOOLKIT */
8019 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8023 case GraphicsExpose
: /* This occurs when an XCopyArea's
8024 source area was obscured or not
8026 f
= x_window_to_frame (dpyinfo
, event
->xgraphicsexpose
.drawable
);
8029 expose_frame (f
, event
->xgraphicsexpose
.x
,
8030 event
->xgraphicsexpose
.y
,
8031 event
->xgraphicsexpose
.width
,
8032 event
->xgraphicsexpose
.height
);
8034 x_clear_under_internal_border (f
);
8036 show_back_buffer (f
);
8038 #ifdef USE_X_TOOLKIT
8041 #endif /* USE_X_TOOLKIT */
8044 case NoExpose
: /* This occurs when an XCopyArea's
8045 source area was completely
8050 /* Redo the mouse-highlight after the tooltip has gone. */
8051 if (event
->xunmap
.window
== tip_window
)
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
);
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
);
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
);
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 */
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;
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 ();
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 ())
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)
8148 || !EQ (f
->tool_bar_window
, hlinfo
->mouse_face_window
))
8152 clear_mouse_face (hlinfo
);
8153 hlinfo
->mouse_face_hidden
= true;
8156 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
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 */
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
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
);
8189 Lisp_Object coding_system
= Qlatin_1
;
8191 /* Event will be modified. */
8192 XKeyEvent xkey
= event
->xkey
;
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
8199 *finish
= X_EVENT_DROP
;
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
));
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
,
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
,
8243 /* Xutf8LookupString is a new but already deprecated interface. -stef */
8244 if (status_return
== XLookupNone
)
8246 else if (status_return
== XLookupChars
)
8251 else if (status_return
!= XLookupKeySym
8252 && status_return
!= XLookupBoth
)
8256 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
8257 copy_bufsiz
, &keysym
,
8260 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
8261 copy_bufsiz
, &keysym
,
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)
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
);
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
;
8289 /* Keysyms directly mapped to Unicode characters. */
8290 if (keysym
>= 0x01000000 && keysym
<= 0x0110FFFF)
8292 if (keysym
< 0x01000080)
8293 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
8295 inev
.ie
.kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
8296 inev
.ie
.code
= keysym
& 0xFFFFFF;
8300 /* Now non-ASCII. */
8301 if (HASH_TABLE_P (Vx_keysym_table
)
8302 && (c
= Fgethash (make_number (keysym
),
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
);
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
)
8321 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
8322 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
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
)
8330 #ifdef XK_dead_circumflex
8331 || orig_keysym
== XK_dead_circumflex
8333 #ifdef XK_dead_grave
8334 || orig_keysym
== XK_dead_grave
8336 #ifdef XK_dead_tilde
8337 || orig_keysym
== XK_dead_tilde
8339 #ifdef XK_dead_diaeresis
8340 || orig_keysym
== XK_dead_diaeresis
8342 #ifdef XK_dead_macron
8343 || orig_keysym
== XK_dead_macron
8345 #ifdef XK_dead_degree
8346 || orig_keysym
== XK_dead_degree
8348 #ifdef XK_dead_acute
8349 || orig_keysym
== XK_dead_acute
8351 #ifdef XK_dead_cedilla
8352 || orig_keysym
== XK_dead_cedilla
8354 #ifdef XK_dead_breve
8355 || orig_keysym
== XK_dead_breve
8357 #ifdef XK_dead_ogonek
8358 || orig_keysym
== XK_dead_ogonek
8360 #ifdef XK_dead_caron
8361 || orig_keysym
== XK_dead_caron
8363 #ifdef XK_dead_doubleacute
8364 || orig_keysym
== XK_dead_doubleacute
8366 #ifdef XK_dead_abovedot
8367 || orig_keysym
== XK_dead_abovedot
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
)
8386 STORE_KEYSYM_FOR_DEBUG (keysym
);
8387 /* make_lispy_event will convert this to a symbolic
8389 inev
.ie
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8390 inev
.ie
.code
= keysym
;
8394 { /* Raw bytes, not keysym. */
8398 for (i
= 0, nchars
= 0; i
< nbytes
; i
++)
8400 if (ASCII_CHAR_P (copy_bufptr
[i
]))
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
,
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
)
8435 if (nchars
== nbytes
)
8436 ch
= copy_bufptr
[i
], len
= 1;
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
);
8443 kbd_buffer_store_buffered_event (&inev
, hold_quit
);
8448 inev
.ie
.kind
= NO_EVENT
; /* Already stored above. */
8450 if (keysym
== NoSymbol
)
8453 /* FIXME: check side effects and remove this. */
8454 ((XEvent
*) event
)->xkey
= xkey
;
8458 /* Don't dispatch this event since XtDispatchEvent calls
8459 XFilterEvent, and two calls in a row may freeze the
8467 x_display_set_last_user_time (dpyinfo
, event
->xkey
.time
);
8469 /* Don't dispatch this event since XtDispatchEvent calls
8470 XFilterEvent, and two calls in a row may freeze the
8478 x_display_set_last_user_time (dpyinfo
, event
->xcrossing
.time
);
8479 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
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
);
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
);
8499 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
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
);
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
)
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
);
8532 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
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
);
8551 if (f
&& xg_event_is_for_scrollbar (f
, event
))
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
;
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);
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
))
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
);
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. */
8661 if (f
&& FRAME_X_DOUBLE_BUFFERED_P (f
))
8662 font_drop_xrender_surfaces (f
);
8665 if (f
) x_cr_destroy_surface (f
);
8670 && configureEvent
.xconfigure
.window
== FRAME_X_WINDOW (f
))
8673 if (FRAME_X_DOUBLE_BUFFERED_P (f
))
8674 font_drop_xrender_surfaces (f
);
8676 xg_frame_resized (f
, configureEvent
.xconfigure
.width
,
8677 configureEvent
.xconfigure
.height
);
8679 x_cr_destroy_surface (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
;
8705 #ifndef USE_X_TOOLKIT
8708 FRAME_PIXEL_TO_TEXT_WIDTH (f
, configureEvent
.xconfigure
.width
);
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 */
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
)))
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
);
8750 unsigned int dummy_uint
;
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
);
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
);
8768 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
8769 xic_set_statusarea (f
);
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
;
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
8802 struct frame
*hf
= dpyinfo
->x_highlight_frame
;
8804 if (FRAME_PARENT_FRAME (f
) || (hf
&& frame_ancestor_p (f
, hf
)))
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
));
8817 if (f
&& xg_event_is_for_scrollbar (f
, event
))
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
)))
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 */
8842 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8843 if (! popup_activated ())
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;
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);
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
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 */
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 */
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. */
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 ()
8911 /* Gtk+ menus only react to the first three buttons. */
8912 && event
->xbutton
.button
< 3
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
;
8932 #endif /* USE_X_TOOLKIT || USE_GTK */
8936 case CirculateNotify
:
8939 case CirculateRequest
:
8942 case VisibilityNotify
:
8946 /* Someone has changed the keyboard mapping - update the
8948 switch (event
->xmapping
.request
)
8950 case MappingModifier
:
8951 x_find_modifier_meanings (dpyinfo
);
8953 case MappingKeyboard
:
8954 XRefreshKeyboardMapping ((XMappingEvent
*) &event
->xmapping
);
8959 xft_settings_event (dpyinfo
, event
);
8964 #ifdef USE_X_TOOLKIT
8966 if (*finish
!= X_EVENT_DROP
)
8967 XtDispatchEvent ((XEvent
*) event
);
8969 #endif /* USE_X_TOOLKIT */
8974 if (inev
.ie
.kind
!= NO_EVENT
)
8976 kbd_buffer_store_buffered_event (&inev
, hold_quit
);
8981 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
8986 XSETFRAME (frame
, f
);
8992 any_help_event_p
= true;
8993 gen_help_event (help_echo_string
, frame
, help_echo_window
,
8994 help_echo_object
, help_echo_pos
);
8998 help_echo_string
= Qnil
;
8999 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
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 ();
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
);
9025 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
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
9039 XTread_socket (struct terminal
*terminal
, struct input_event
*hold_quit
)
9042 bool event_found
= false;
9043 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
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
);
9055 while (XPending (dpyinfo
->display
))
9060 XNextEvent (dpyinfo
->display
, &event
);
9063 /* Filter events for the current X input method. */
9064 if (x_filter_event (dpyinfo
, &event
))
9069 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
9071 if (finish
== X_EVENT_GOTO_OUT
)
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
;
9094 current_hold_quit
= 0;
9096 if (current_finish
== X_EVENT_GOTO_OUT
)
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.) */
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 */
9109 if (x_noop_count
>= 100)
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
;
9139 /***********************************************************************
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. */
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. */
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
);
9180 struct glyph
*cursor_glyph
;
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
)
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
);
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
;
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.
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
9236 cursor_glyph
= get_phys_cursor_glyph (w
);
9237 if (cursor_glyph
== NULL
)
9240 /* Experimental avoidance of cursor on xwidget. */
9241 if (cursor_glyph
->type
== XWIDGET_GLYPH
)
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
);
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
);
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
;
9270 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
9271 xgcv
.graphics_exposures
= False
;
9274 XChangeGC (dpy
, gc
, mask
, &xgcv
);
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
);
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
);
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. */
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. */
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. */
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
));
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
);
9374 switch (cursor_type
)
9376 case HOLLOW_BOX_CURSOR
:
9377 x_draw_hollow_cursor (w
, glyph_row
);
9380 case FILLED_BOX_CURSOR
:
9381 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
9385 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
9389 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
9393 w
->phys_cursor_width
= 0;
9402 if (w
== XWINDOW (f
->selected_window
))
9403 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
9404 xic_set_preeditarea (w
, x
, y
);
9408 XFlush (FRAME_X_DISPLAY (f
));
9414 /* Make the x-window of frame F use the gnu icon bitmap. */
9417 x_bitmap_icon (struct frame
*f
, Lisp_Object file
)
9419 ptrdiff_t bitmap_id
;
9421 if (FRAME_X_WINDOW (f
) == 0)
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;
9432 /* Use gtk_window_set_icon_from_file () if available,
9433 It's not restricted to bitmaps */
9434 if (xg_set_icon (f
, file
))
9436 #endif /* USE_GTK */
9437 bitmap_id
= x_create_bitmap_from_file (f
, file
);
9438 x_create_bitmap_mask (f
, bitmap_id
);
9442 /* Create the GNU bitmap and mask if necessary. */
9443 if (FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
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;
9456 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
9458 rc
= x_create_bitmap_from_xpm_data (f
, gnu_xpm_bits
);
9460 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
9464 /* If all else fails, use the (black and white) xbm image. */
9467 rc
= x_create_bitmap_from_data (f
, (char *) gnu_xbm_bits
,
9468 gnu_xbm_width
, gnu_xbm_height
);
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
;
9493 /* Make the x-window of frame F use a rectangle with text.
9494 Use ICON_NAME as the text. */
9497 x_text_icon (struct frame
*f
, const char *icon_name
)
9499 if (FRAME_X_WINDOW (f
) == 0)
9504 text
.value
= (unsigned char *) icon_name
;
9505 text
.encoding
= XA_STRING
;
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);
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
];
9531 x_special_error_handler handler
;
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. */
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
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. */
9569 x_catch_errors_with_handler (Display
*dpy
, x_special_error_handler handler
,
9572 struct x_error_message_stack
*data
= xmalloc (sizeof *data
);
9574 /* Make sure any errors from previous requests have been dealt with. */
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
;
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. */
9599 x_uncatch_errors_after_check (void)
9601 struct x_error_message_stack
*tmp
;
9604 tmp
= x_error_message
;
9605 x_error_message
= x_error_message
->prev
;
9610 /* Undo the last x_catch_errors call.
9611 DPY should be the display that was passed to x_catch_errors. */
9614 x_uncatch_errors (void)
9616 struct x_error_message_stack
*tmp
;
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
;
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. */
9636 x_check_errors (Display
*dpy
, const char *format
)
9638 /* Make sure to catch any errors incurred so far. */
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. */
9654 x_had_errors_p (Display
*dpy
)
9656 /* Make sure to catch any errors incurred so far. */
9659 return x_error_message
->string
[0] != 0;
9662 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
9665 x_clear_errors (Display
*dpy
)
9667 x_error_message
->string
[0] = 0;
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. */
9676 x_fully_uncatch_errors (void)
9678 while (x_error_message
)
9679 x_uncatch_errors ();
9684 static unsigned int x_wire_count
;
9687 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
9692 /************************************************************************
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
);
9718 /* Protect display from being closed when we delete the last
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
;
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. */
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. */
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",
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. */
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));
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. */
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
)
9825 if (x_error_message
)
9826 x_error_catcher (display
, event
);
9828 x_error_quitter (display
, event
);
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
)
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
)
9871 snprintf (buf
, sizeof buf
, "Connection lost to X server '%s'",
9872 DisplayString (display
));
9873 x_connection_closed (display
, buf
, true);
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
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
;
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
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
);
9912 /* Compute character columns occupied by scrollbar.
9914 Don't do things differently for non-toolkit scrollbars
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
;
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,
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
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 */
9952 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
9955 xic_set_xfontset (f
, SSDATA (fontset_ascii (fontset
)));
9964 /***********************************************************************
9966 ***********************************************************************/
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. */
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
;
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
);
10001 #endif /* HAVE_X11R6 */
10003 /* Open the connection to the XIM server on display DPYINFO.
10004 RESOURCE_NAME is the resource name Emacs uses. */
10007 xim_open_dpy (struct x_display_info
*dpyinfo
, char *resource_name
)
10015 XCloseIM (dpyinfo
->xim
);
10016 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
10018 dpyinfo
->xim
= xim
;
10023 XIMCallback destroy
;
10026 /* Get supported styles and XIM values. */
10027 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
10030 destroy
.callback
= xim_destroy_callback
;
10031 destroy
.client_data
= (XPointer
)dpyinfo
;
10032 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
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. */
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. */
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
;
10069 FOR_EACH_FRAME (tail
, frame
)
10071 struct frame
*f
= XFRAME (frame
);
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
);
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. */
10101 xim_initialize (struct x_display_info
*dpyinfo
, char *resource_name
)
10103 dpyinfo
->xim
= NULL
;
10107 #ifdef HAVE_X11R6_XIM
10108 struct xim_inst_t
*xim_inst
= xmalloc (sizeof *xim_inst
);
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. */
10132 xim_close_dpy (struct x_display_info
*dpyinfo
)
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
);
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. */
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
)))
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
10185 if (f
->output_data
.x
->has_been_visible
&& !p
)
10188 Lisp_Object edges
= Qnil
;
10190 XSETFRAME (frame
, f
);
10191 edges
= Fx_frame_edges (frame
, Qouter_edges
);
10193 width
= (XINT (Fnth (make_number (2), edges
))
10194 - XINT (Fnth (make_number (0), edges
)));
10198 f
->left_pos
= (FRAME_PIXEL_WIDTH (p
) - width
- 2 * f
->border_width
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
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
);
10226 if (f
->output_data
.x
->has_been_visible
&& !p
)
10229 Lisp_Object edges
= Qnil
;
10231 XSETFRAME (frame
, f
);
10233 edges
= Fx_frame_edges (frame
, Qouter_edges
);
10235 height
= (XINT (Fnth (make_number (3), edges
))
10236 - XINT (Fnth (make_number (1), edges
)));
10240 f
->top_pos
= (FRAME_PIXEL_HEIGHT (p
) - height
- 2 * f
->border_width
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. */
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)
10267 f
->left_pos
= xoff
;
10268 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10270 f
->size_hint_flags
|= XNegative
;
10272 f
->size_hint_flags
|= YNegative
;
10273 f
->win_gravity
= NorthWestGravity
;
10276 x_calc_absolute_position (f
);
10279 x_wm_set_size_hint (f
, 0, false);
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
);
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
;
10308 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
10309 modified_left
, modified_top
);
10311 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10312 modified_left
, modified_top
);
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
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
);
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. */
10346 x_wm_supports (struct frame
*f
, Atom want_atom
)
10349 unsigned long actual_size
, bytes_remaining
;
10350 int i
, rc
, actual_format
;
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
;
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 ();
10377 wmcheck_window
= *(Window
*) 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 ();
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
;
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 ();
10414 dpyinfo
->net_supported_atoms
= (Atom
*)tmp_data
;
10415 dpyinfo
->nr_net_supported_atoms
= actual_size
;
10416 dpyinfo
->net_supported_window
= wmcheck_window
;
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 ();
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
,
10438 /* 1 = add, 0 = remove */
10440 (make_number (add
),
10442 (make_fixnum_or_float (atom
),
10444 ? list1 (make_fixnum_or_float (value
))
10449 x_set_sticky (struct frame
*f
, Lisp_Object new_value
, Lisp_Object old_value
)
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.
10471 x_set_skip_taskbar (struct frame
*f
, Lisp_Object new_value
, Lisp_Object old_value
)
10473 if (!EQ (new_value
, old_value
))
10476 xg_set_skip_taskbar (f
, new_value
);
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
);
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.
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. */
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
;
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. */
10553 get_current_wm_state (struct frame
*f
,
10558 unsigned long actual_size
;
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. */
10566 xcb_get_property_cookie_t prop_cookie
;
10567 xcb_get_property_reply_t
*prop
;
10568 xcb_atom_t
*reply_data
;
10570 Display
*dpy
= FRAME_X_DISPLAY (f
);
10571 unsigned long bytes_remaining
;
10572 int rc
, actual_format
;
10574 unsigned char *tmp_data
= NULL
;
10579 *size_state
= FULLSCREEN_NONE
;
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
);
10598 is_hidden
= FRAME_ICONIFIED_P (f
);
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
;
10612 is_hidden
= FRAME_ICONIFIED_P (f
);
10615 x_uncatch_errors ();
10618 for (i
= 0; i
< actual_size
; ++i
)
10620 Atom a
= reply_data
[i
];
10621 if (a
== dpyinfo
->Xatom_net_wm_state_hidden
)
10623 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_horz
)
10625 if (*size_state
== FULLSCREEN_HEIGHT
)
10626 *size_state
= FULLSCREEN_MAXIMIZED
;
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
;
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
)
10646 if (tmp_data
) XFree (tmp_data
);
10650 return ! is_hidden
;
10653 /* Do fullscreen as specified in extended window manager hints */
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
);
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
)
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
,
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
);
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
);
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
);
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
);
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
);
10753 if (cur
== FULLSCREEN_BOTH
)
10754 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
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
);
10763 set_wm_state (frame
, true,
10764 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10765 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10768 case FULLSCREEN_NONE
:
10769 if (cur
== FULLSCREEN_BOTH
)
10770 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
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
;
10786 XTfullscreen_hook (struct frame
*f
)
10788 if (FRAME_VISIBLE_P (f
))
10791 x_check_fullscreen (f
);
10799 x_handle_net_wm_state (struct frame
*f
, const XPropertyEvent
*event
)
10801 int value
= FULLSCREEN_NONE
;
10803 bool sticky
= false;
10804 bool not_hidden
= get_current_wm_state (f
, event
->window
, &value
, &sticky
);
10809 case FULLSCREEN_WIDTH
:
10812 case FULLSCREEN_HEIGHT
:
10813 lval
= Qfullheight
;
10815 case FULLSCREEN_BOTH
:
10818 case FULLSCREEN_MAXIMIZED
:
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
);
10833 /* Check if we need to resize the frame due to a fullscreen request.
10834 If so needed, resize the frame. */
10836 x_check_fullscreen (struct frame
*f
)
10838 Lisp_Object lval
= Qnil
;
10840 if (do_ewmh_fullscreen (f
))
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
:
10860 width
= x_display_pixel_width (dpyinfo
);
10861 height
= x_display_pixel_height (dpyinfo
);
10863 case FULLSCREEN_BOTH
:
10865 width
= x_display_pixel_width (dpyinfo
);
10866 height
= x_display_pixel_height (dpyinfo
);
10868 case FULLSCREEN_WIDTH
:
10870 width
= x_display_pixel_width (dpyinfo
);
10871 height
= height
+ FRAME_MENUBAR_HEIGHT (f
);
10873 case FULLSCREEN_HEIGHT
:
10874 lval
= Qfullheight
;
10875 height
= x_display_pixel_height (dpyinfo
);
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
),
10889 if (FRAME_VISIBLE_P (f
))
10890 x_wait_for_event (f
, ConfigureNotify
);
10893 change_frame_size (f
, width
, height
- FRAME_MENUBAR_HEIGHT (f
),
10894 false, true, false, true);
10899 /* `x_net_wm_state' might have reset the fullscreen frame parameter,
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. */
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
, ¤t_left
, ¤t_top
);
10922 if (current_left
!= expected_left
|| current_top
!= expected_top
)
10924 /* It's a "Type A" window manager. */
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);
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. */
10958 x_sync_with_move (struct frame
*f
, int left
, int top
, bool fuzzy
)
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
10970 XSync (FRAME_X_DISPLAY (f
), False
);
10971 x_real_positions (f
, ¤t_left
, ¤t_top
);
10975 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
10978 if (eabs (current_left
- left
) <= 10
10979 && eabs (current_top
- top
) <= 40)
10982 else if (current_left
== left
&& current_top
== top
)
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. */
10995 x_wait_for_event (struct frame
*f
, int eventtype
)
10997 int level
= interrupt_input_blocked
;
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. */
11016 interrupt_input_blocked
= level
;
11021 time_now
= current_timespec ();
11022 if (timespec_cmp (tmo_at
, time_now
) < 0)
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. */
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
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
);
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
));
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
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
);
11132 change_frame_size (f
, width
, height
, false, true, false, true);
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. */
11144 x_set_window_size (struct frame
*f
, bool change_gravity
,
11145 int width
, int height
, bool pixelwise
)
11149 /* The following breaks our calculations. If it's really needed,
11150 think of something else. */
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
11167 pixelh
-= FRAME_MENUBAR_HEIGHT (f
);
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);
11176 /* Pixelize width and height, if necessary. */
11179 width
= width
* FRAME_COLUMN_WIDTH (f
);
11180 height
= height
* FRAME_LINE_HEIGHT (f
);
11184 if (FRAME_GTK_WIDGET (f
))
11185 xg_frame_set_char_size (f
, width
, height
);
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
);
11204 do_pending_window_change (false);
11207 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11210 frame_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
)
11214 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11215 0, 0, 0, 0, pix_x
, pix_y
);
11219 /* Raise frame F. */
11222 x_raise_frame (struct frame
*f
)
11225 if (FRAME_VISIBLE_P (f
))
11226 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
11227 XFlush (FRAME_X_DISPLAY (f
));
11231 /* Lower frame F. */
11234 x_lower_frame (struct frame
*f
)
11236 if (FRAME_VISIBLE_P (f
))
11239 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
11240 XFlush (FRAME_X_DISPLAY (f
));
11245 /* Request focus with XEmbed */
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 */
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
))
11270 XSETFRAME (frame
, f
);
11271 x_send_client_event (frame
, make_number (0), frame
,
11272 dpyinfo
->Xatom_net_active_window
,
11274 list2i (1, dpyinfo
->last_user_time
));
11279 XTframe_raise_lower (struct frame
*f
, bool raise_flag
)
11287 /* XEmbed implementation. */
11289 #if defined USE_X_TOOLKIT || ! defined USE_GTK
11291 /* XEmbed implementation. */
11293 #define XEMBED_VERSION 0
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
;
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 */
11311 xembed_send_message (struct frame
*f
, Time t
, enum xembed_message msg
,
11312 long int detail
, long int data1
, long int data2
)
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. */
11337 x_make_frame_visible (struct frame
*f
)
11339 if (FRAME_PARENT_FRAME (f
))
11341 if (!FRAME_VISIBLE_P (f
))
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
);
11349 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
11353 SET_FRAME_VISIBLE (f
, true);
11354 SET_FRAME_ICONIFIED (f
, false);
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
);
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 */
11388 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
11389 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
11391 if (FRAME_X_EMBEDDED_P (f
))
11392 xembed_set_info (f
, XEMBED_MAPPED
);
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. */
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
)
11436 unsigned int width
, height
, border
, depth
;
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
);
11459 /* Change from mapped state to withdrawn state. */
11461 /* Make the frame visible (mapped and not iconified). */
11464 x_make_frame_invisible (struct frame
*f
)
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;
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);
11485 if (FRAME_GTK_OUTER_WIDGET (f
))
11486 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
11489 if (FRAME_X_EMBEDDED_P (f
))
11490 xembed_set_info (f
, 0);
11494 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11495 DefaultScreen (FRAME_X_DISPLAY (f
))))
11498 error ("Can't notify window manager of window withdrawal");
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);
11514 /* Change window state from mapped to iconified. */
11517 x_iconify_frame (struct frame
*f
)
11519 #ifdef USE_X_TOOLKIT
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
))
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);
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);
11565 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11566 XtWindow (f
->output_data
.x
->widget
),
11567 DefaultScreen (FRAME_X_DISPLAY (f
)));
11571 error ("Can't notify window manager of iconification");
11573 SET_FRAME_ICONIFIED (f
, true);
11574 SET_FRAME_VISIBLE (f
, 0);
11577 XFlush (FRAME_X_DISPLAY (f
));
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. */
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
)),
11605 SubstructureRedirectMask
| SubstructureNotifyMask
,
11609 error ("Can't notify window manager of iconification");
11613 /* X11R3: set the initial_state field of the window manager hints to
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
));
11628 #endif /* not USE_X_TOOLKIT */
11632 /* Free X resources of frame F. */
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
11641 struct scroll_bar
*b
;
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
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
);
11678 free_frame_xic (f
);
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 */
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
);
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
);
11781 /* Destroy the X window of frame F. */
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. */
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
);
11816 #ifdef USE_X_TOOLKIT
11817 if (f
->output_data
.x
->widget
)
11819 widget_update_wm_size_hints (f
->output_data
.x
->widget
);
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. */
11864 size_hints
.flags
|= flags
;
11869 XSizeHints hints
; /* Sometimes I hate X Windows... */
11870 long supplied_return
;
11873 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11877 size_hints
.flags
|= flags
;
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
;
11896 size_hints
.win_gravity
= f
->win_gravity
;
11897 size_hints
.flags
|= PWinGravity
;
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 */
11913 x_wm_set_window_state (struct frame
*f
, int state
)
11915 #ifdef USE_X_TOOLKIT
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 */
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
);
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
;
11948 /* It seems there is no way to turn off use of an icon
11956 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
);
11960 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
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 */
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 /***********************************************************************
11993 ***********************************************************************/
11997 /* Check that FONT is valid on frame F. It is if it can be found in F's
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 /***********************************************************************
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. */
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))
12060 if (! strncmp (name2
, "unix:", 5))
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
++)
12081 if (seen_colon
&& *name1
== '.')
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
12093 get_bits_and_offset (unsigned long mask
, int *bits
, int *offset
)
12098 while (!(mask
& 1))
12114 /* Return true iff display DISPLAY is available for use.
12115 But don't permanently open it, just test its availability. */
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
);
12126 XCloseDisplay (dpy
);
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
);
12140 /* Create invisible cursor on X display referred by DPYINFO. */
12143 make_invisible_cursor (struct x_display_info
*dpyinfo
)
12145 Display
*dpy
= dpyinfo
->display
;
12146 static char const no_data
[] = { 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
)
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
)
12162 XFreePixmap (dpy
, pix
);
12165 x_uncatch_errors ();
12170 /* True if DPY supports Xfixes extension >= 4. */
12173 x_probe_xfixes_extension (Display
*dpy
)
12177 return XFixesQueryVersion (dpy
, &major
, &minor
) && major
>= 4;
12180 #endif /* HAVE_XFIXES */
12183 /* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
12186 xfixes_toggle_visible_pointer (struct frame
*f
, bool invisible
)
12190 XFixesHideCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12192 XFixesShowCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
12193 f
->pointer_invisible
= invisible
;
12196 #endif /* HAVE_XFIXES */
12199 /* Toggle mouse pointer visibility on frame F by using invisible cursor. */
12202 x_toggle_visible_pointer (struct frame
*f
, bool invisible
)
12204 eassert (FRAME_DISPLAY_INFO (f
)->invisible_cursor
!= 0);
12206 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
12207 FRAME_DISPLAY_INFO (f
)->invisible_cursor
);
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. */
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
;
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
)
12242 struct terminal
*terminal
;
12243 struct x_display_info
*dpyinfo
;
12246 xcb_connection_t
*xcb_conn
;
12251 if (!x_initialized
)
12257 if (! x_display_ok (SSDATA (display_name
)))
12258 error ("Display %s can't be opened", SSDATA (display_name
));
12262 #define NUM_ARGV 10
12264 char *argv
[NUM_ARGV
];
12265 char **argv2
= argv
;
12268 if (x_initialized
++ > 1)
12270 xg_display_open (SSDATA (display_name
), &dpy
);
12274 static char display_opt
[] = "--display";
12275 static char name_opt
[] = "--name";
12277 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
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. */
12305 unrequest_sigio (); /* See comment in x_display_ok. */
12306 gtk_init (&argc
, &argv2
);
12310 g_log_remove_handler ("GLib", id
);
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
));
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
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
);
12349 argv
[0] = (char *) "";
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
),
12363 turn_on_atimers (true);
12365 #ifdef HAVE_X11XTR6
12366 /* I think this is to compensate for XtSetLanguageProc. */
12371 #else /* not USE_X_TOOLKIT */
12372 XSetLocaleModifiers ("");
12373 unrequest_sigio (); /* See comment in x_display_ok. */
12374 dpy
= XOpenDisplay (SSDATA (display_name
));
12376 #endif /* not USE_X_TOOLKIT */
12377 #endif /* not USE_GTK*/
12379 /* Detect failure. */
12387 xcb_conn
= XGetXCBConnection (dpy
);
12391 xg_display_close (dpy
);
12393 #ifdef USE_X_TOOLKIT
12394 XtCloseDisplay (dpy
);
12396 XCloseDisplay (dpy
);
12398 #endif /* ! USE_GTK */
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
)))
12418 terminal
->kboard
= share
->terminal
->kboard
;
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
;
12430 kset_system_key_alist
12432 call1 (Qvendor_specific_keysyms
,
12433 vendor
? build_string (vendor
) : empty_unibyte_string
));
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
);
12456 dpyinfo
->xcb_connection
= xcb_conn
;
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
);
12467 XSetAfterFunction (x_current_display
, x_trace_wire
);
12470 Lisp_Object system_name
= Fsystem_name ();
12472 if (INT_ADD_WRAPV (SBYTES (Vinvocation_name
), SBYTES (system_name
) + 2,
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
);
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. */
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
);
12501 dpyinfo
->display
->db
= xrdb
;
12503 /* Put the rdb where we can find it in a way that works on
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");
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
);
12545 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
12546 dpyinfo
->visual
, AllocNone
);
12549 dpyinfo
->supports_xdbe
= false;
12552 if (XdbeQueryExtension (dpyinfo
->display
, &xdbe_major
, &xdbe_minor
))
12553 dpyinfo
->supports_xdbe
= true;
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
;
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
;
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
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
)
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
)
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
);
12703 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12704 gray_bits
, gray_width
, gray_height
,
12707 x_setup_pointer_blanking (dpyinfo
);
12710 xim_initialize (dpyinfo
, resource_name
);
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
);
12720 fcntl (dpyinfo
->connection
, F_SETOWN
, getpid ());
12721 #endif /* ! defined (F_SETOWN) */
12723 if (interrupt_input
)
12724 init_sigio (dpyinfo
->connection
);
12728 XrmValue d
, fr
, to
;
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
))
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 ();
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
,
12768 if (STRINGP (value
)
12769 && (!strcmp (SSDATA (value
), "false")
12770 || !strcmp (SSDATA (value
), "off")))
12773 if (STRINGP (value
)
12774 && (!strcmp (SSDATA (value
), "true")
12775 || !strcmp (SSDATA (value
), "on")))
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
);
12789 x_extension_initialize (dpyinfo
);
12797 /* Get rid of display DPYINFO, deleting all frames on it,
12798 and without sending any more commands to the X server. */
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
12808 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
12809 if (t
->type
== output_x_window
&& t
->display_info
.x
== dpyinfo
)
12812 /* Close X session management when we close its display. */
12813 if (t
->id
== 1 && x_session_have_connection ())
12814 x_session_close ();
12816 delete_terminal (t
);
12820 if (next_noop_dpyinfo
== dpyinfo
)
12821 next_noop_dpyinfo
= dpyinfo
->next
;
12823 if (x_display_list
== dpyinfo
)
12824 x_display_list
= dpyinfo
->next
;
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
;
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
);
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. */
12857 x_process_timeouts (struct atimer
*timer
)
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 ();
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. */
12880 x_activate_timeout_atimer (void)
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;
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
,
12903 x_clear_end_of_line
,
12905 x_after_update_window_line
,
12906 x_update_window_begin
,
12907 x_update_window_end
,
12909 x_clear_window_mouse_face
,
12910 x_get_glyph_overhangs
,
12911 x_fix_overlapping_area
,
12912 x_draw_fringe_bitmap
,
12914 x_cr_define_fringe_bitmap
,
12915 x_cr_destroy_fringe_bitmap
,
12917 0, /* define_fringe_bitmap */
12918 0, /* destroy_fringe_bitmap */
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. */
12933 /* This function is called when the last frame on a display is deleted. */
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
)
12946 /* We must close our connection to the XIM server before closing the
12949 xim_close_dpy (dpyinfo
);
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. */
12973 #ifdef HAVE_XRMSETDATABASE
12974 XrmSetDatabase (dpyinfo
->display
, NULL
);
12976 dpyinfo
->display
->db
= NULL
;
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
);
12985 xg_display_close (dpyinfo
->display
);
12987 #ifdef USE_X_TOOLKIT
12988 XtCloseDisplay (dpyinfo
->display
);
12990 XCloseDisplay (dpyinfo
->display
);
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
);
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
;
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. */
13060 x_initialize (void)
13065 any_help_event_p
= false;
13066 ignore_next_mouse_click_timeout
= 0;
13069 current_count
= -1;
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)
13079 "Warning: An error occurred initializing X11 thread support!\n");
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
);
13098 #ifdef USE_TOOLKIT_SCROLL_BARS
13100 xaw3d_arrow_scroll
= False
;
13101 xaw3d_pick_top
= True
;
13106 x_cr_init_fringe (&x_redisplay_interface
);
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
);
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");
13126 syms_of_xterm (void)
13128 x_error_message
= NULL
;
13130 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
13131 DEFSYM (Qlatin_1
, "latin-1");
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");
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
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
13176 Vx_toolkit_scroll_bars
= intern_c_string ("motif");
13177 #elif defined HAVE_XAW3D
13178 Vx_toolkit_scroll_bars
= intern_c_string ("xaw3d");
13180 Vx_toolkit_scroll_bars
= intern_c_string ("gtk");
13182 Vx_toolkit_scroll_bars
= intern_c_string ("xaw");
13185 Vx_toolkit_scroll_bars
= Qnil
;
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
,
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
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;