1 /* X Communication module for terminals which understand the X protocol.
3 Copyright (C) 1989, 1993-2016 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
10 (at 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. */
30 #include "blockinput.h"
32 /* This may include sys/types.h, and that somehow loses
33 if this is not done before the other system files. */
35 #include <X11/cursorfont.h>
37 /* If we have Xfixes extension, use it for pointer blanking. */
39 #include <X11/extensions/Xfixes.h>
42 /* Using Xft implies that XRender is available. */
44 #include <X11/extensions/Xrender.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
53 #include <sys/ioctl.h>
60 #include "character.h"
62 #include "composite.h"
64 #include "dispextern.h"
66 #include "termhooks.h"
69 #include "emacs-icon.h"
75 #include "xsettings.h"
76 #include "sysselect.h"
80 #include <X11/Shell.h>
88 #include <X11/Xproto.h>
92 #if defined (USE_LUCID) || defined (USE_MOTIF)
93 #include "../lwlib/xlwmenu.h"
97 #if !defined (NO_EDITRES)
99 extern void _XEditResCheckMessages (Widget
, XtPointer
, XEvent
*, Boolean
*);
100 #endif /* not NO_EDITRES */
102 /* Include toolkit specific headers for the scroll bar widget. */
104 #ifdef USE_TOOLKIT_SCROLL_BARS
105 #if defined USE_MOTIF
106 #include <Xm/Xm.h> /* For LESSTIF_VERSION */
107 #include <Xm/ScrollBar.h>
108 #else /* !USE_MOTIF i.e. use Xaw */
111 #include <X11/Xaw3d/Simple.h>
112 #include <X11/Xaw3d/Scrollbar.h>
113 #include <X11/Xaw3d/ThreeD.h>
114 #else /* !HAVE_XAW3D */
115 #include <X11/Xaw/Simple.h>
116 #include <X11/Xaw/Scrollbar.h>
117 #endif /* !HAVE_XAW3D */
119 #define XtNpickTop "pickTop"
120 #endif /* !XtNpickTop */
121 #endif /* !USE_MOTIF */
122 #endif /* USE_TOOLKIT_SCROLL_BARS */
124 #endif /* USE_X_TOOLKIT */
128 #ifndef XtNinitialState
129 #define XtNinitialState "initialState"
133 #include "bitmaps/gray.xbm"
136 #include <X11/XKBlib.h>
139 /* Default to using XIM if available. */
143 bool use_xim
= false; /* configure --without-xim */
146 /* Non-zero means that a HELP_EVENT has been generated since Emacs
149 static bool any_help_event_p
;
151 /* This is a chain of structures for all the X displays currently in
154 struct x_display_info
*x_display_list
;
158 /* The application context for Xt use. */
159 XtAppContext Xt_app_con
;
160 static String Xt_default_resources
[] = {0};
162 /* Non-zero means user is interacting with a toolkit scroll bar. */
163 static bool toolkit_scroll_bar_interaction
;
165 #endif /* USE_X_TOOLKIT */
167 /* Non-zero timeout value means ignore next mouse click if it arrives
168 before that timeout elapses (i.e. as part of the same sequence of
169 events resulting from clicking on a frame to select it). */
171 static Time ignore_next_mouse_click_timeout
;
173 /* Used locally within XTread_socket. */
175 static int x_noop_count
;
178 /* The name of the Emacs icon file. */
179 static Lisp_Object xg_default_icon_file
;
182 /* Some functions take this as char *, not const char *. */
183 static char emacs_class
[] = EMACS_CLASS
;
187 XEMBED_MAPPED
= 1 << 0
192 XEMBED_EMBEDDED_NOTIFY
= 0,
193 XEMBED_WINDOW_ACTIVATE
= 1,
194 XEMBED_WINDOW_DEACTIVATE
= 2,
195 XEMBED_REQUEST_FOCUS
= 3,
197 XEMBED_FOCUS_OUT
= 5,
198 XEMBED_FOCUS_NEXT
= 6,
199 XEMBED_FOCUS_PREV
= 7,
201 XEMBED_MODALITY_ON
= 10,
202 XEMBED_MODALITY_OFF
= 11,
203 XEMBED_REGISTER_ACCELERATOR
= 12,
204 XEMBED_UNREGISTER_ACCELERATOR
= 13,
205 XEMBED_ACTIVATE_ACCELERATOR
= 14
208 static void x_free_cr_resources (struct frame
*);
209 static bool x_alloc_nearest_color_1 (Display
*, Colormap
, XColor
*);
210 static void x_raise_frame (struct frame
*);
211 static void x_lower_frame (struct frame
*);
212 static int x_io_error_quitter (Display
*);
213 static struct terminal
*x_create_terminal (struct x_display_info
*);
214 static void x_frame_rehighlight (struct x_display_info
*);
216 static void x_clip_to_row (struct window
*, struct glyph_row
*,
217 enum glyph_row_area
, GC
);
218 static struct scroll_bar
*x_window_to_scroll_bar (Display
*, Window
, int);
219 static void x_scroll_bar_report_motion (struct frame
**, Lisp_Object
*,
220 enum scroll_bar_part
*,
221 Lisp_Object
*, Lisp_Object
*,
223 static void x_horizontal_scroll_bar_report_motion (struct frame
**, Lisp_Object
*,
224 enum scroll_bar_part
*,
225 Lisp_Object
*, Lisp_Object
*,
227 static bool x_handle_net_wm_state (struct frame
*, const XPropertyEvent
*);
228 static void x_check_fullscreen (struct frame
*);
229 static void x_check_expected_move (struct frame
*, int, int);
230 static void x_sync_with_move (struct frame
*, int, int, bool);
231 static int handle_one_xevent (struct x_display_info
*,
232 const XEvent
*, int *,
233 struct input_event
*);
234 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
235 static int x_dispatch_event (XEvent
*, Display
*);
237 static void x_wm_set_window_state (struct frame
*, int);
238 static void x_wm_set_icon_pixmap (struct frame
*, ptrdiff_t);
239 static void x_initialize (void);
241 static bool get_current_wm_state (struct frame
*, Window
, int *, bool *);
243 /* Flush display of frame F. */
246 x_flush (struct frame
*f
)
248 eassert (f
&& FRAME_X_P (f
));
249 /* Don't call XFlush when it is not safe to redisplay; the X
250 connection may be broken. */
251 if (!NILP (Vinhibit_redisplay
))
255 XFlush (FRAME_X_DISPLAY (f
));
260 /* Remove calls to XFlush by defining XFlush to an empty replacement.
261 Calls to XFlush should be unnecessary because the X output buffer
262 is flushed automatically as needed by calls to XPending,
263 XNextEvent, or XWindowEvent according to the XFlush man page.
264 XTread_socket calls XPending. Removing XFlush improves
267 #define XFlush(DISPLAY) (void) 0
270 /***********************************************************************
272 ***********************************************************************/
276 /* This is a function useful for recording debugging information about
277 the sequence of occurrences in this file. */
285 struct record event_record
[100];
287 int event_record_index
;
290 record_event (char *locus
, int type
)
292 if (event_record_index
== ARRAYELTS (event_record
))
293 event_record_index
= 0;
295 event_record
[event_record_index
].locus
= locus
;
296 event_record
[event_record_index
].type
= type
;
297 event_record_index
++;
304 #define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
305 #define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
307 static struct x_gc_ext_data
*
308 x_gc_get_ext_data (struct frame
*f
, GC gc
, int create_if_not_found_p
)
310 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
312 XExtData
**head
, *ext_data
;
315 head
= XEHeadOfExtensionList (object
);
316 ext_data
= XFindOnExtensionList (head
, dpyinfo
->ext_codes
->extension
);
317 if (ext_data
== NULL
)
319 if (!create_if_not_found_p
)
323 ext_data
= xzalloc (sizeof (*ext_data
));
324 ext_data
->number
= dpyinfo
->ext_codes
->extension
;
325 ext_data
->private_data
= xzalloc (sizeof (struct x_gc_ext_data
));
326 XAddToExtensionList (head
, ext_data
);
329 return (struct x_gc_ext_data
*) ext_data
->private_data
;
333 x_extension_initialize (struct x_display_info
*dpyinfo
)
335 XExtCodes
*ext_codes
= XAddExtension (dpyinfo
->display
);
337 dpyinfo
->ext_codes
= ext_codes
;
341 x_cr_destroy_surface (struct frame
*f
)
343 if (FRAME_CR_SURFACE (f
))
345 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
346 cairo_surface_destroy (FRAME_CR_SURFACE (f
));
347 FRAME_CR_SURFACE (f
) = 0;
348 if (cr
) cairo_destroy (cr
);
349 FRAME_CR_CONTEXT (f
) = NULL
;
354 x_begin_cr_clip (struct frame
*f
, GC gc
)
356 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
361 if (! FRAME_CR_SURFACE (f
))
363 cairo_surface_t
*surface
;
364 surface
= cairo_xlib_surface_create (FRAME_X_DISPLAY (f
),
366 FRAME_DISPLAY_INFO (f
)->visual
,
367 FRAME_PIXEL_WIDTH (f
),
368 FRAME_PIXEL_HEIGHT (f
));
369 cr
= cairo_create (surface
);
370 cairo_surface_destroy (surface
);
373 cr
= cairo_create (FRAME_CR_SURFACE (f
));
374 FRAME_CR_CONTEXT (f
) = cr
;
380 struct x_gc_ext_data
*gc_ext
= x_gc_get_ext_data (f
, gc
, 0);
382 if (gc_ext
&& gc_ext
->n_clip_rects
)
386 for (i
= 0; i
< gc_ext
->n_clip_rects
; i
++)
387 cairo_rectangle (cr
, gc_ext
->clip_rects
[i
].x
,
388 gc_ext
->clip_rects
[i
].y
,
389 gc_ext
->clip_rects
[i
].width
,
390 gc_ext
->clip_rects
[i
].height
);
399 x_end_cr_clip (struct frame
*f
)
401 cairo_restore (FRAME_CR_CONTEXT (f
));
405 x_set_cr_source_with_gc_foreground (struct frame
*f
, GC gc
)
410 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, GCForeground
, &xgcv
);
411 color
.pixel
= xgcv
.foreground
;
412 x_query_color (f
, &color
);
413 cairo_set_source_rgb (FRAME_CR_CONTEXT (f
), color
.red
/ 65535.0,
414 color
.green
/ 65535.0, color
.blue
/ 65535.0);
418 x_set_cr_source_with_gc_background (struct frame
*f
, GC gc
)
423 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, GCBackground
, &xgcv
);
424 color
.pixel
= xgcv
.background
;
425 x_query_color (f
, &color
);
426 cairo_set_source_rgb (FRAME_CR_CONTEXT (f
), color
.red
/ 65535.0,
427 color
.green
/ 65535.0, color
.blue
/ 65535.0);
430 /* Fringe bitmaps. */
432 static int max_fringe_bmp
= 0;
433 static cairo_pattern_t
**fringe_bmp
= 0;
436 x_cr_define_fringe_bitmap (int which
, unsigned short *bits
, int h
, int wd
)
439 cairo_surface_t
*surface
;
441 cairo_pattern_t
*pattern
;
443 if (which
>= max_fringe_bmp
)
446 max_fringe_bmp
= which
+ 20;
447 fringe_bmp
= (cairo_pattern_t
**) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (cairo_pattern_t
*));
448 while (i
< max_fringe_bmp
)
454 surface
= cairo_image_surface_create (CAIRO_FORMAT_A1
, wd
, h
);
455 stride
= cairo_image_surface_get_stride (surface
);
456 data
= cairo_image_surface_get_data (surface
);
458 for (i
= 0; i
< h
; i
++)
460 *((unsigned short *) data
) = bits
[i
];
464 cairo_surface_mark_dirty (surface
);
465 pattern
= cairo_pattern_create_for_surface (surface
);
466 cairo_surface_destroy (surface
);
470 fringe_bmp
[which
] = pattern
;
474 x_cr_destroy_fringe_bitmap (int which
)
476 if (which
>= max_fringe_bmp
)
479 if (fringe_bmp
[which
])
482 cairo_pattern_destroy (fringe_bmp
[which
]);
485 fringe_bmp
[which
] = 0;
489 x_cr_draw_image (struct frame
*f
, GC gc
, cairo_pattern_t
*image
,
490 int src_x
, int src_y
, int width
, int height
,
491 int dest_x
, int dest_y
, bool overlay_p
)
494 cairo_matrix_t matrix
;
495 cairo_surface_t
*surface
;
496 cairo_format_t format
;
498 cr
= x_begin_cr_clip (f
, gc
);
500 cairo_rectangle (cr
, dest_x
, dest_y
, width
, height
);
503 x_set_cr_source_with_gc_background (f
, gc
);
504 cairo_rectangle (cr
, dest_x
, dest_y
, width
, height
);
505 cairo_fill_preserve (cr
);
508 cairo_matrix_init_translate (&matrix
, src_x
- dest_x
, src_y
- dest_y
);
509 cairo_pattern_set_matrix (image
, &matrix
);
510 cairo_pattern_get_surface (image
, &surface
);
511 format
= cairo_image_surface_get_format (surface
);
512 if (format
!= CAIRO_FORMAT_A8
&& format
!= CAIRO_FORMAT_A1
)
514 cairo_set_source (cr
, image
);
519 x_set_cr_source_with_gc_foreground (f
, gc
);
520 cairo_mask (cr
, image
);
526 x_cr_draw_frame (cairo_t
*cr
, struct frame
*f
)
530 width
= FRAME_PIXEL_WIDTH (f
);
531 height
= FRAME_PIXEL_HEIGHT (f
);
533 x_free_cr_resources (f
);
534 FRAME_CR_CONTEXT (f
) = cr
;
535 x_clear_area (f
, 0, 0, width
, height
);
536 expose_frame (f
, 0, 0, width
, height
);
537 FRAME_CR_CONTEXT (f
) = NULL
;
540 static cairo_status_t
541 x_cr_accumulate_data (void *closure
, const unsigned char *data
,
544 Lisp_Object
*acc
= (Lisp_Object
*) closure
;
546 *acc
= Fcons (make_unibyte_string ((char const *) data
, length
), *acc
);
548 return CAIRO_STATUS_SUCCESS
;
552 x_cr_destroy (Lisp_Object arg
)
554 cairo_t
*cr
= (cairo_t
*) XSAVE_POINTER (arg
, 0);
562 x_cr_export_frames (Lisp_Object frames
, cairo_surface_type_t surface_type
)
565 cairo_surface_t
*surface
;
568 void (*surface_set_size_func
) (cairo_surface_t
*, double, double) = NULL
;
569 Lisp_Object acc
= Qnil
;
570 int count
= SPECPDL_INDEX ();
572 specbind (Qredisplay_dont_pause
, Qt
);
573 redisplay_preserve_echo_area (31);
575 f
= XFRAME (XCAR (frames
));
576 frames
= XCDR (frames
);
577 width
= FRAME_PIXEL_WIDTH (f
);
578 height
= FRAME_PIXEL_HEIGHT (f
);
581 #ifdef CAIRO_HAS_PDF_SURFACE
582 if (surface_type
== CAIRO_SURFACE_TYPE_PDF
)
584 surface
= cairo_pdf_surface_create_for_stream (x_cr_accumulate_data
, &acc
,
586 surface_set_size_func
= cairo_pdf_surface_set_size
;
590 #ifdef CAIRO_HAS_PNG_FUNCTIONS
591 if (surface_type
== CAIRO_SURFACE_TYPE_IMAGE
)
592 surface
= cairo_image_surface_create (CAIRO_FORMAT_RGB24
, width
, height
);
595 #ifdef CAIRO_HAS_PS_SURFACE
596 if (surface_type
== CAIRO_SURFACE_TYPE_PS
)
598 surface
= cairo_ps_surface_create_for_stream (x_cr_accumulate_data
, &acc
,
600 surface_set_size_func
= cairo_ps_surface_set_size
;
604 #ifdef CAIRO_HAS_SVG_SURFACE
605 if (surface_type
== CAIRO_SURFACE_TYPE_SVG
)
606 surface
= cairo_svg_surface_create_for_stream (x_cr_accumulate_data
, &acc
,
612 cr
= cairo_create (surface
);
613 cairo_surface_destroy (surface
);
614 record_unwind_protect (x_cr_destroy
, make_save_ptr (cr
));
618 x_free_cr_resources (f
);
619 FRAME_CR_CONTEXT (f
) = cr
;
620 x_clear_area (f
, 0, 0, width
, height
);
621 expose_frame (f
, 0, 0, width
, height
);
622 FRAME_CR_CONTEXT (f
) = NULL
;
627 cairo_surface_show_page (surface
);
628 f
= XFRAME (XCAR (frames
));
629 frames
= XCDR (frames
);
630 width
= FRAME_PIXEL_WIDTH (f
);
631 height
= FRAME_PIXEL_HEIGHT (f
);
632 if (surface_set_size_func
)
633 (*surface_set_size_func
) (surface
, width
, height
);
640 #ifdef CAIRO_HAS_PNG_FUNCTIONS
641 if (surface_type
== CAIRO_SURFACE_TYPE_IMAGE
)
643 cairo_surface_flush (surface
);
644 cairo_surface_write_to_png_stream (surface
, x_cr_accumulate_data
, &acc
);
649 unbind_to (count
, Qnil
);
651 return CALLN (Fapply
, intern ("concat"), Fnreverse (acc
));
654 #endif /* USE_CAIRO */
657 x_free_cr_resources (struct frame
*f
)
662 Lisp_Object rest
, frame
;
663 FOR_EACH_FRAME (rest
, frame
)
664 if (FRAME_X_P (XFRAME (frame
)))
665 x_free_cr_resources (XFRAME (frame
));
669 cairo_t
*cr
= FRAME_CR_CONTEXT (f
);
673 cairo_surface_t
*surface
= cairo_get_target (cr
);
675 if (cairo_surface_get_type (surface
) == CAIRO_SURFACE_TYPE_XLIB
)
678 FRAME_CR_CONTEXT (f
) = NULL
;
686 x_set_clip_rectangles (struct frame
*f
, GC gc
, XRectangle
*rectangles
, int n
)
688 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, rectangles
, n
, Unsorted
);
690 eassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
693 struct x_gc_ext_data
*gc_ext
= x_gc_get_ext_data (f
, gc
, 1);
695 gc_ext
->n_clip_rects
= n
;
696 memcpy (gc_ext
->clip_rects
, rectangles
, sizeof (XRectangle
) * n
);
702 x_reset_clip_rectangles (struct frame
*f
, GC gc
)
704 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
707 struct x_gc_ext_data
*gc_ext
= x_gc_get_ext_data (f
, gc
, 0);
710 gc_ext
->n_clip_rects
= 0;
716 x_fill_rectangle (struct frame
*f
, GC gc
, int x
, int y
, int width
, int height
)
721 cr
= x_begin_cr_clip (f
, gc
);
722 x_set_cr_source_with_gc_foreground (f
, gc
);
723 cairo_rectangle (cr
, x
, y
, width
, height
);
727 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
728 gc
, x
, y
, width
, height
);
733 x_draw_rectangle (struct frame
*f
, GC gc
, int x
, int y
, int width
, int height
)
738 cr
= x_begin_cr_clip (f
, gc
);
739 x_set_cr_source_with_gc_foreground (f
, gc
);
740 cairo_rectangle (cr
, x
+ 0.5, y
+ 0.5, width
, height
);
741 cairo_set_line_width (cr
, 1);
745 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
746 gc
, x
, y
, width
, height
);
751 x_clear_window (struct frame
*f
)
756 cr
= x_begin_cr_clip (f
, NULL
);
757 x_set_cr_source_with_gc_background (f
, f
->output_data
.x
->normal_gc
);
761 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
767 x_fill_trapezoid_for_relief (struct frame
*f
, GC gc
, int x
, int y
,
768 int width
, int height
, int top_p
)
772 cr
= x_begin_cr_clip (f
, gc
);
773 x_set_cr_source_with_gc_foreground (f
, gc
);
774 cairo_move_to (cr
, top_p
? x
: x
+ height
, y
);
775 cairo_line_to (cr
, x
, y
+ height
);
776 cairo_line_to (cr
, top_p
? x
+ width
- height
: x
+ width
, y
+ height
);
777 cairo_line_to (cr
, x
+ width
, y
);
784 CORNER_BOTTOM_RIGHT
, /* 0 -> pi/2 */
785 CORNER_BOTTOM_LEFT
, /* pi/2 -> pi */
786 CORNER_TOP_LEFT
, /* pi -> 3pi/2 */
787 CORNER_TOP_RIGHT
, /* 3pi/2 -> 2pi */
792 x_erase_corners_for_relief (struct frame
*f
, GC gc
, int x
, int y
,
793 int width
, int height
,
794 double radius
, double margin
, int corners
)
799 cr
= x_begin_cr_clip (f
, gc
);
800 x_set_cr_source_with_gc_background (f
, gc
);
801 for (i
= 0; i
< CORNER_LAST
; i
++)
802 if (corners
& (1 << i
))
804 double xm
, ym
, xc
, yc
;
806 if (i
== CORNER_TOP_LEFT
|| i
== CORNER_BOTTOM_LEFT
)
807 xm
= x
- margin
, xc
= xm
+ radius
;
809 xm
= x
+ width
+ margin
, xc
= xm
- radius
;
810 if (i
== CORNER_TOP_LEFT
|| i
== CORNER_TOP_RIGHT
)
811 ym
= y
- margin
, yc
= ym
+ radius
;
813 ym
= y
+ height
+ margin
, yc
= ym
- radius
;
815 cairo_move_to (cr
, xm
, ym
);
816 cairo_arc (cr
, xc
, yc
, radius
, i
* M_PI_2
, (i
+ 1) * M_PI_2
);
819 cairo_rectangle (cr
, x
, y
, width
, height
);
825 x_draw_horizontal_wave (struct frame
*f
, GC gc
, int x
, int y
,
826 int width
, int height
, int wave_length
)
829 double dx
= wave_length
, dy
= height
- 1;
832 cr
= x_begin_cr_clip (f
, gc
);
833 x_set_cr_source_with_gc_foreground (f
, gc
);
834 cairo_rectangle (cr
, x
, y
, width
, height
);
839 xoffset
= x
% (wave_length
* 2);
841 xoffset
= wave_length
* 2;
844 xoffset
= x
% (wave_length
* 2) + wave_length
* 2;
845 n
= (width
+ xoffset
) / wave_length
+ 1;
846 if (xoffset
> wave_length
)
848 xoffset
-= wave_length
;
854 cairo_move_to (cr
, x
- xoffset
+ 0.5, y
+ 0.5);
857 cairo_rel_line_to (cr
, dx
, dy
);
860 cairo_set_line_width (cr
, 1);
867 /* Return the struct x_display_info corresponding to DPY. */
869 struct x_display_info
*
870 x_display_info_for_display (Display
*dpy
)
872 struct x_display_info
*dpyinfo
;
874 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
875 if (dpyinfo
->display
== dpy
)
882 x_find_topmost_parent (struct frame
*f
)
884 struct x_output
*x
= f
->output_data
.x
;
885 Window win
= None
, wi
= x
->parent_desc
;
886 Display
*dpy
= FRAME_X_DISPLAY (f
);
888 while (wi
!= FRAME_DISPLAY_INFO (f
)->root_window
)
892 unsigned int nchildren
;
895 if (XQueryTree (dpy
, win
, &root
, &wi
, &children
, &nchildren
))
904 #define OPAQUE 0xffffffff
907 x_set_frame_alpha (struct frame
*f
)
909 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
910 Display
*dpy
= FRAME_X_DISPLAY (f
);
911 Window win
= FRAME_OUTER_WINDOW (f
);
913 double alpha_min
= 1.0;
917 if (dpyinfo
->x_highlight_frame
== f
)
922 if (FLOATP (Vframe_alpha_lower_limit
))
923 alpha_min
= XFLOAT_DATA (Vframe_alpha_lower_limit
);
924 else if (INTEGERP (Vframe_alpha_lower_limit
))
925 alpha_min
= (XINT (Vframe_alpha_lower_limit
)) / 100.0;
929 else if (alpha
> 1.0)
931 else if (0.0 <= alpha
&& alpha
< alpha_min
&& alpha_min
<= 1.0)
934 opac
= alpha
* OPAQUE
;
936 x_catch_errors (dpy
);
938 /* If there is a parent from the window manager, put the property there
939 also, to work around broken window managers that fail to do that.
940 Do this unconditionally as this function is called on reparent when
941 alpha has not changed on the frame. */
943 parent
= x_find_topmost_parent (f
);
945 XChangeProperty (dpy
, parent
, dpyinfo
->Xatom_net_wm_window_opacity
,
946 XA_CARDINAL
, 32, PropModeReplace
,
947 (unsigned char *) &opac
, 1);
949 /* return unless necessary */
954 unsigned long n
, left
;
956 rc
= XGetWindowProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
957 0, 1, False
, XA_CARDINAL
,
958 &actual
, &format
, &n
, &left
,
961 if (rc
== Success
&& actual
!= None
)
963 unsigned long value
= *(unsigned long *)data
;
973 XChangeProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
974 XA_CARDINAL
, 32, PropModeReplace
,
975 (unsigned char *) &opac
, 1);
979 /***********************************************************************
980 Starting and ending an update
981 ***********************************************************************/
983 /* Start an update of frame F. This function is installed as a hook
984 for update_begin, i.e. it is called when update_begin is called.
985 This function is called prior to calls to x_update_window_begin for
986 each window being updated. Currently, there is nothing to do here
987 because all interesting stuff is done on a window basis. */
990 x_update_begin (struct frame
*f
)
993 if (! NILP (tip_frame
) && XFRAME (tip_frame
) == f
994 && ! FRAME_VISIBLE_P (f
))
997 if (! FRAME_CR_SURFACE (f
))
1001 if (FRAME_GTK_WIDGET (f
))
1003 GdkWindow
*w
= gtk_widget_get_window (FRAME_GTK_WIDGET (f
));
1004 width
= gdk_window_get_width (w
);
1005 height
= gdk_window_get_height (w
);
1010 width
= FRAME_PIXEL_WIDTH (f
);
1011 height
= FRAME_PIXEL_HEIGHT (f
);
1012 if (! FRAME_EXTERNAL_TOOL_BAR (f
))
1013 height
+= FRAME_TOOL_BAR_HEIGHT (f
);
1014 if (! FRAME_EXTERNAL_MENU_BAR (f
))
1015 height
+= FRAME_MENU_BAR_HEIGHT (f
);
1018 if (width
> 0 && height
> 0)
1021 FRAME_CR_SURFACE (f
) = cairo_image_surface_create
1022 (CAIRO_FORMAT_ARGB32
, width
, height
);
1026 #endif /* USE_CAIRO */
1029 /* Start update of window W. */
1032 x_update_window_begin (struct window
*w
)
1034 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1035 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (f
);
1037 w
->output_cursor
= w
->cursor
;
1041 if (f
== hlinfo
->mouse_face_mouse_frame
)
1043 /* Don't do highlighting for mouse motion during the update. */
1044 hlinfo
->mouse_face_defer
= true;
1046 /* If F needs to be redrawn, simply forget about any prior mouse
1048 if (FRAME_GARBAGED_P (f
))
1049 hlinfo
->mouse_face_window
= Qnil
;
1056 /* Draw a vertical window border from (x,y0) to (x,y1) */
1059 x_draw_vertical_window_border (struct window
*w
, int x
, int y0
, int y1
)
1061 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1064 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1066 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
1070 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
, x
, y0
, 1, y1
- y0
);
1072 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1073 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
1077 /* Draw a window divider from (x0,y0) to (x1,y1) */
1080 x_draw_window_divider (struct window
*w
, int x0
, int x1
, int y0
, int y1
)
1082 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1083 struct face
*face
= FACE_FROM_ID (f
, WINDOW_DIVIDER_FACE_ID
);
1084 struct face
*face_first
= FACE_FROM_ID (f
, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID
);
1085 struct face
*face_last
= FACE_FROM_ID (f
, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID
);
1086 unsigned long color
= face
? face
->foreground
: FRAME_FOREGROUND_PIXEL (f
);
1087 unsigned long color_first
= (face_first
1088 ? face_first
->foreground
1089 : FRAME_FOREGROUND_PIXEL (f
));
1090 unsigned long color_last
= (face_last
1091 ? face_last
->foreground
1092 : FRAME_FOREGROUND_PIXEL (f
));
1093 Display
*display
= FRAME_X_DISPLAY (f
);
1095 if (y1
- y0
> x1
- x0
&& x1
- x0
> 2)
1098 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_first
);
1099 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1100 x0
, y0
, 1, y1
- y0
);
1101 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
1102 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1103 x0
+ 1, y0
, x1
- x0
- 2, y1
- y0
);
1104 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_last
);
1105 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1106 x1
- 1, y0
, 1, y1
- y0
);
1108 else if (x1
- x0
> y1
- y0
&& y1
- y0
> 3)
1111 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_first
);
1112 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1113 x0
, y0
, x1
- x0
, 1);
1114 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
1115 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1116 x0
, y0
+ 1, x1
- x0
, y1
- y0
- 2);
1117 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_last
);
1118 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1119 x0
, y1
- 1, x1
- x0
, 1);
1123 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
1124 x_fill_rectangle (f
, f
->output_data
.x
->normal_gc
,
1125 x0
, y0
, x1
- x0
, y1
- y0
);
1129 /* End update of window W.
1131 Draw vertical borders between horizontally adjacent windows, and
1132 display W's cursor if CURSOR_ON_P is non-zero.
1134 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1135 glyphs in mouse-face were overwritten. In that case we have to
1136 make sure that the mouse-highlight is properly redrawn.
1138 W may be a menu bar pseudo-window in case we don't have X toolkit
1139 support. Such windows don't have a cursor, so don't display it
1143 x_update_window_end (struct window
*w
, bool cursor_on_p
,
1144 bool mouse_face_overwritten_p
)
1146 if (!w
->pseudo_window_p
)
1151 display_and_set_cursor (w
, true,
1152 w
->output_cursor
.hpos
, w
->output_cursor
.vpos
,
1153 w
->output_cursor
.x
, w
->output_cursor
.y
);
1155 if (draw_window_fringes (w
, true))
1157 if (WINDOW_RIGHT_DIVIDER_WIDTH (w
))
1158 x_draw_right_divider (w
);
1160 x_draw_vertical_border (w
);
1166 /* If a row with mouse-face was overwritten, arrange for
1167 XTframe_up_to_date to redisplay the mouse highlight. */
1168 if (mouse_face_overwritten_p
)
1170 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (XFRAME (w
->frame
));
1172 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
1173 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
1174 hlinfo
->mouse_face_window
= Qnil
;
1179 /* End update of frame F. This function is installed as a hook in
1183 x_update_end (struct frame
*f
)
1185 /* Mouse highlight may be displayed again. */
1186 MOUSE_HL_INFO (f
)->mouse_face_defer
= false;
1189 if (FRAME_CR_SURFACE (f
))
1193 #if defined (USE_GTK) && defined (HAVE_GTK3)
1194 if (FRAME_GTK_WIDGET (f
))
1196 GdkWindow
*w
= gtk_widget_get_window (FRAME_GTK_WIDGET (f
));
1197 cr
= gdk_cairo_create (w
);
1202 cairo_surface_t
*surface
;
1203 int width
= FRAME_PIXEL_WIDTH (f
);
1204 int height
= FRAME_PIXEL_HEIGHT (f
);
1205 if (! FRAME_EXTERNAL_TOOL_BAR (f
))
1206 height
+= FRAME_TOOL_BAR_HEIGHT (f
);
1207 if (! FRAME_EXTERNAL_MENU_BAR (f
))
1208 height
+= FRAME_MENU_BAR_HEIGHT (f
);
1209 surface
= cairo_xlib_surface_create (FRAME_X_DISPLAY (f
),
1211 FRAME_DISPLAY_INFO (f
)->visual
,
1214 cr
= cairo_create (surface
);
1215 cairo_surface_destroy (surface
);
1218 cairo_set_source_surface (cr
, FRAME_CR_SURFACE (f
), 0, 0);
1223 #endif /* USE_CAIRO */
1227 XFlush (FRAME_X_DISPLAY (f
));
1233 /* This function is called from various places in xdisp.c
1234 whenever a complete update has been performed. */
1237 XTframe_up_to_date (struct frame
*f
)
1240 FRAME_MOUSE_UPDATE (f
);
1244 /* Clear under internal border if any (GTK has its own version). */
1247 x_clear_under_internal_border (struct frame
*f
)
1249 if (FRAME_INTERNAL_BORDER_WIDTH (f
) > 0)
1251 int border
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1252 int width
= FRAME_PIXEL_WIDTH (f
);
1253 int height
= FRAME_PIXEL_HEIGHT (f
);
1254 int margin
= FRAME_TOP_MARGIN_HEIGHT (f
);
1257 x_clear_area (f
, 0, 0, border
, height
);
1258 x_clear_area (f
, 0, margin
, width
, border
);
1259 x_clear_area (f
, width
- border
, 0, border
, height
);
1260 x_clear_area (f
, 0, height
- border
, width
, border
);
1266 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1267 arrow bitmaps, or clear the fringes if no bitmaps are required
1268 before DESIRED_ROW is made current. This function is called from
1269 update_window_line only if it is known that there are differences
1270 between bitmaps to be drawn between current row and DESIRED_ROW. */
1273 x_after_update_window_line (struct window
*w
, struct glyph_row
*desired_row
)
1277 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1278 desired_row
->redraw_fringe_bitmaps_p
= true;
1280 #ifdef USE_X_TOOLKIT
1281 /* When a window has disappeared, make sure that no rest of
1282 full-width rows stays visible in the internal border. Could
1283 check here if updated window is the leftmost/rightmost window,
1284 but I guess it's not worth doing since vertically split windows
1285 are almost never used, internal border is rarely set, and the
1286 overhead is very small. */
1291 if (windows_or_buffers_changed
1292 && desired_row
->full_width_p
1293 && (f
= XFRAME (w
->frame
),
1294 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1296 && (height
= desired_row
->visible_height
,
1299 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1302 x_clear_area (f
, 0, y
, width
, height
);
1303 x_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1311 x_draw_fringe_bitmap (struct window
*w
, struct glyph_row
*row
, struct draw_fringe_bitmap_params
*p
)
1313 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1314 Display
*display
= FRAME_X_DISPLAY (f
);
1315 Window window
= FRAME_X_WINDOW (f
);
1316 GC gc
= f
->output_data
.x
->normal_gc
;
1317 struct face
*face
= p
->face
;
1319 /* Must clip because of partially visible lines. */
1320 x_clip_to_row (w
, row
, ANY_AREA
, gc
);
1322 if (p
->bx
>= 0 && !p
->overlay_p
)
1324 /* In case the same realized face is used for fringes and
1325 for something displayed in the text (e.g. face `region' on
1326 mono-displays, the fill style may have been changed to
1327 FillSolid in x_draw_glyph_string_background. */
1329 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
1331 XSetForeground (display
, face
->gc
, face
->background
);
1333 x_fill_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1336 XSetForeground (display
, face
->gc
, face
->foreground
);
1340 if (p
->which
&& p
->which
< max_fringe_bmp
)
1344 XGetGCValues (display
, gc
, GCForeground
| GCBackground
, &gcv
);
1345 XSetForeground (display
, gc
, (p
->cursor_p
1346 ? (p
->overlay_p
? face
->background
1347 : f
->output_data
.x
->cursor_pixel
)
1348 : face
->foreground
));
1349 XSetBackground (display
, gc
, face
->background
);
1350 x_cr_draw_image (f
, gc
, fringe_bmp
[p
->which
], 0, p
->dh
,
1351 p
->wd
, p
->h
, p
->x
, p
->y
, p
->overlay_p
);
1352 XSetForeground (display
, gc
, gcv
.foreground
);
1353 XSetBackground (display
, gc
, gcv
.background
);
1355 #else /* not USE_CAIRO */
1359 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
1360 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
1364 bits
= (char *) (p
->bits
+ p
->dh
);
1366 bits
= (char *) p
->bits
+ p
->dh
;
1368 /* Draw the bitmap. I believe these small pixmaps can be cached
1370 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
1372 ? (p
->overlay_p
? face
->background
1373 : f
->output_data
.x
->cursor_pixel
)
1374 : face
->foreground
),
1375 face
->background
, depth
);
1379 clipmask
= XCreatePixmapFromBitmapData (display
,
1380 FRAME_DISPLAY_INFO (f
)->root_window
,
1383 gcv
.clip_mask
= clipmask
;
1384 gcv
.clip_x_origin
= p
->x
;
1385 gcv
.clip_y_origin
= p
->y
;
1386 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
1389 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
1390 p
->wd
, p
->h
, p
->x
, p
->y
);
1391 XFreePixmap (display
, pixmap
);
1395 gcv
.clip_mask
= (Pixmap
) 0;
1396 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
1397 XFreePixmap (display
, clipmask
);
1400 #endif /* not USE_CAIRO */
1402 x_reset_clip_rectangles (f
, gc
);
1405 /***********************************************************************
1407 ***********************************************************************/
1411 static void x_set_glyph_string_clipping (struct glyph_string
*);
1412 static void x_set_glyph_string_gc (struct glyph_string
*);
1413 static void x_draw_glyph_string_foreground (struct glyph_string
*);
1414 static void x_draw_composite_glyph_string_foreground (struct glyph_string
*);
1415 static void x_draw_glyph_string_box (struct glyph_string
*);
1416 static void x_draw_glyph_string (struct glyph_string
*);
1417 static _Noreturn
void x_delete_glyphs (struct frame
*, int);
1418 static void x_compute_glyph_string_overhangs (struct glyph_string
*);
1419 static void x_set_cursor_gc (struct glyph_string
*);
1420 static void x_set_mode_line_face_gc (struct glyph_string
*);
1421 static void x_set_mouse_face_gc (struct glyph_string
*);
1422 static bool x_alloc_lighter_color (struct frame
*, Display
*, Colormap
,
1423 unsigned long *, double, int);
1424 static void x_setup_relief_color (struct frame
*, struct relief
*,
1425 double, int, unsigned long);
1426 static void x_setup_relief_colors (struct glyph_string
*);
1427 static void x_draw_image_glyph_string (struct glyph_string
*);
1428 static void x_draw_image_relief (struct glyph_string
*);
1429 static void x_draw_image_foreground (struct glyph_string
*);
1430 static void x_draw_image_foreground_1 (struct glyph_string
*, Pixmap
);
1431 static void x_clear_glyph_string_rect (struct glyph_string
*, int,
1433 static void x_draw_relief_rect (struct frame
*, int, int, int, int,
1434 int, bool, bool, bool, bool, bool,
1436 static void x_draw_box_rect (struct glyph_string
*, int, int, int, int,
1437 int, bool, bool, XRectangle
*);
1438 static void x_scroll_bar_clear (struct frame
*);
1441 static void x_check_font (struct frame
*, struct font
*);
1445 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1449 x_set_cursor_gc (struct glyph_string
*s
)
1451 if (s
->font
== FRAME_FONT (s
->f
)
1452 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1453 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1455 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
1458 /* Cursor on non-default face: must merge. */
1462 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
1463 xgcv
.foreground
= s
->face
->background
;
1465 /* If the glyph would be invisible, try a different foreground. */
1466 if (xgcv
.foreground
== xgcv
.background
)
1467 xgcv
.foreground
= s
->face
->foreground
;
1468 if (xgcv
.foreground
== xgcv
.background
)
1469 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
1470 if (xgcv
.foreground
== xgcv
.background
)
1471 xgcv
.foreground
= s
->face
->foreground
;
1473 /* Make sure the cursor is distinct from text in this face. */
1474 if (xgcv
.background
== s
->face
->background
1475 && xgcv
.foreground
== s
->face
->foreground
)
1477 xgcv
.background
= s
->face
->foreground
;
1478 xgcv
.foreground
= s
->face
->background
;
1481 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1482 xgcv
.graphics_exposures
= False
;
1483 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
1485 if (FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1486 XChangeGC (s
->display
, FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1489 FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1490 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1492 s
->gc
= FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1497 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1500 x_set_mouse_face_gc (struct glyph_string
*s
)
1505 /* What face has to be used last for the mouse face? */
1506 face_id
= MOUSE_HL_INFO (s
->f
)->mouse_face_face_id
;
1507 face
= FACE_FROM_ID (s
->f
, face_id
);
1509 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1511 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1512 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1514 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1515 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1516 prepare_face_for_display (s
->f
, s
->face
);
1518 if (s
->font
== s
->face
->font
)
1519 s
->gc
= s
->face
->gc
;
1522 /* Otherwise construct scratch_cursor_gc with values from FACE
1527 xgcv
.background
= s
->face
->background
;
1528 xgcv
.foreground
= s
->face
->foreground
;
1529 xgcv
.graphics_exposures
= False
;
1530 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
1532 if (FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1533 XChangeGC (s
->display
, FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1536 FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1537 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1539 s
->gc
= FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1542 eassert (s
->gc
!= 0);
1546 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1547 Faces to use in the mode line have already been computed when the
1548 matrix was built, so there isn't much to do, here. */
1551 x_set_mode_line_face_gc (struct glyph_string
*s
)
1553 s
->gc
= s
->face
->gc
;
1557 /* Set S->gc of glyph string S for drawing that glyph string. Set
1558 S->stippled_p to a non-zero value if the face of S has a stipple
1562 x_set_glyph_string_gc (struct glyph_string
*s
)
1564 prepare_face_for_display (s
->f
, s
->face
);
1566 if (s
->hl
== DRAW_NORMAL_TEXT
)
1568 s
->gc
= s
->face
->gc
;
1569 s
->stippled_p
= s
->face
->stipple
!= 0;
1571 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1573 x_set_mode_line_face_gc (s
);
1574 s
->stippled_p
= s
->face
->stipple
!= 0;
1576 else if (s
->hl
== DRAW_CURSOR
)
1578 x_set_cursor_gc (s
);
1579 s
->stippled_p
= false;
1581 else if (s
->hl
== DRAW_MOUSE_FACE
)
1583 x_set_mouse_face_gc (s
);
1584 s
->stippled_p
= s
->face
->stipple
!= 0;
1586 else if (s
->hl
== DRAW_IMAGE_RAISED
1587 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1589 s
->gc
= s
->face
->gc
;
1590 s
->stippled_p
= s
->face
->stipple
!= 0;
1595 /* GC must have been set. */
1596 eassert (s
->gc
!= 0);
1600 /* Set clipping for output of glyph string S. S may be part of a mode
1601 line or menu if we don't have X toolkit support. */
1604 x_set_glyph_string_clipping (struct glyph_string
*s
)
1606 XRectangle
*r
= s
->clip
;
1607 int n
= get_glyph_string_clip_rects (s
, r
, 2);
1610 x_set_clip_rectangles (s
->f
, s
->gc
, r
, n
);
1615 /* Set SRC's clipping for output of glyph string DST. This is called
1616 when we are drawing DST's left_overhang or right_overhang only in
1620 x_set_glyph_string_clipping_exactly (struct glyph_string
*src
, struct glyph_string
*dst
)
1625 r
.width
= src
->width
;
1627 r
.height
= src
->height
;
1630 x_set_clip_rectangles (dst
->f
, dst
->gc
, &r
, 1);
1635 Compute left and right overhang of glyph string S. */
1638 x_compute_glyph_string_overhangs (struct glyph_string
*s
)
1641 && (s
->first_glyph
->type
== CHAR_GLYPH
1642 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
1644 struct font_metrics metrics
;
1646 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1648 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1649 struct font
*font
= s
->font
;
1652 for (i
= 0; i
< s
->nchars
; i
++)
1653 code
[i
] = (s
->char2b
[i
].byte1
<< 8) | s
->char2b
[i
].byte2
;
1654 font
->driver
->text_extents (font
, code
, s
->nchars
, &metrics
);
1658 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1660 composition_gstring_width (gstring
, s
->cmp_from
, s
->cmp_to
, &metrics
);
1662 s
->right_overhang
= (metrics
.rbearing
> metrics
.width
1663 ? metrics
.rbearing
- metrics
.width
: 0);
1664 s
->left_overhang
= metrics
.lbearing
< 0 ? - metrics
.lbearing
: 0;
1668 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
1669 s
->left_overhang
= - s
->cmp
->lbearing
;
1674 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1677 x_clear_glyph_string_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
1680 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1681 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1682 x_fill_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
1683 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1687 /* Draw the background of glyph_string S. If S->background_filled_p
1688 is non-zero don't draw it. FORCE_P non-zero means draw the
1689 background even if it wouldn't be drawn normally. This is used
1690 when a string preceding S draws into the background of S, or S
1691 contains the first component of a composition. */
1694 x_draw_glyph_string_background (struct glyph_string
*s
, bool force_p
)
1696 /* Nothing to do if background has already been drawn or if it
1697 shouldn't be drawn in the first place. */
1698 if (!s
->background_filled_p
)
1700 int box_line_width
= max (s
->face
->box_line_width
, 0);
1704 /* Fill background with a stipple pattern. */
1705 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1706 x_fill_rectangle (s
->f
, s
->gc
, s
->x
,
1707 s
->y
+ box_line_width
,
1708 s
->background_width
,
1709 s
->height
- 2 * box_line_width
);
1710 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1711 s
->background_filled_p
= true;
1713 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1714 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1715 font dimensions, since the actual glyphs might be
1716 much smaller. So in that case we always clear the
1717 rectangle with background color. */
1718 || FONT_TOO_HIGH (s
->font
)
1719 || s
->font_not_found_p
1720 || s
->extends_to_end_of_line_p
1723 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1724 s
->background_width
,
1725 s
->height
- 2 * box_line_width
);
1726 s
->background_filled_p
= true;
1732 /* Draw the foreground of glyph string S. */
1735 x_draw_glyph_string_foreground (struct glyph_string
*s
)
1739 /* If first glyph of S has a left box line, start drawing the text
1740 of S to the right of that box line. */
1741 if (s
->face
->box
!= FACE_NO_BOX
1742 && s
->first_glyph
->left_box_line_p
)
1743 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1747 /* Draw characters of S as rectangles if S's font could not be
1749 if (s
->font_not_found_p
)
1751 for (i
= 0; i
< s
->nchars
; ++i
)
1753 struct glyph
*g
= s
->first_glyph
+ i
;
1754 x_draw_rectangle (s
->f
,
1755 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1757 x
+= g
->pixel_width
;
1762 struct font
*font
= s
->font
;
1763 int boff
= font
->baseline_offset
;
1766 if (font
->vertical_centering
)
1767 boff
= VCENTER_BASELINE_OFFSET (font
, s
->f
) - boff
;
1769 y
= s
->ybase
- boff
;
1771 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1772 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, false);
1774 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, true);
1775 if (s
->face
->overstrike
)
1776 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, false);
1780 /* Draw the foreground of composite glyph string S. */
1783 x_draw_composite_glyph_string_foreground (struct glyph_string
*s
)
1786 struct font
*font
= s
->font
;
1788 /* If first glyph of S has a left box line, start drawing the text
1789 of S to the right of that box line. */
1790 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1791 && s
->first_glyph
->left_box_line_p
)
1792 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1796 /* S is a glyph string for a composition. S->cmp_from is the index
1797 of the first character drawn for glyphs of this composition.
1798 S->cmp_from == 0 means we are drawing the very first character of
1799 this composition. */
1801 /* Draw a rectangle for the composition if the font for the very
1802 first character of the composition could not be loaded. */
1803 if (s
->font_not_found_p
)
1805 if (s
->cmp_from
== 0)
1806 x_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
1807 s
->width
- 1, s
->height
- 1);
1809 else if (! s
->first_glyph
->u
.cmp
.automatic
)
1813 for (i
= 0, j
= s
->cmp_from
; i
< s
->nchars
; i
++, j
++)
1814 /* TAB in a composition means display glyphs with padding
1815 space on the left or right. */
1816 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1818 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1819 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1821 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, false);
1822 if (s
->face
->overstrike
)
1823 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, false);
1828 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1833 for (i
= j
= s
->cmp_from
; i
< s
->cmp_to
; i
++)
1835 glyph
= LGSTRING_GLYPH (gstring
, i
);
1836 if (NILP (LGLYPH_ADJUSTMENT (glyph
)))
1837 width
+= LGLYPH_WIDTH (glyph
);
1840 int xoff
, yoff
, wadjust
;
1844 font
->driver
->draw (s
, j
, i
, x
, y
, false);
1845 if (s
->face
->overstrike
)
1846 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, false);
1849 xoff
= LGLYPH_XOFF (glyph
);
1850 yoff
= LGLYPH_YOFF (glyph
);
1851 wadjust
= LGLYPH_WADJUST (glyph
);
1852 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, false);
1853 if (s
->face
->overstrike
)
1854 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
+ 1, y
+ yoff
,
1863 font
->driver
->draw (s
, j
, i
, x
, y
, false);
1864 if (s
->face
->overstrike
)
1865 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, false);
1871 /* Draw the foreground of glyph string S for glyphless characters. */
1874 x_draw_glyphless_glyph_string_foreground (struct glyph_string
*s
)
1876 struct glyph
*glyph
= s
->first_glyph
;
1880 /* If first glyph of S has a left box line, start drawing the text
1881 of S to the right of that box line. */
1882 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1883 && s
->first_glyph
->left_box_line_p
)
1884 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1890 for (i
= 0; i
< s
->nchars
; i
++, glyph
++)
1892 char buf
[7], *str
= NULL
;
1893 int len
= glyph
->u
.glyphless
.len
;
1895 if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
)
1898 && CHAR_TABLE_P (Vglyphless_char_display
)
1899 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display
))
1903 = (! glyph
->u
.glyphless
.for_no_font
1904 ? CHAR_TABLE_REF (Vglyphless_char_display
,
1905 glyph
->u
.glyphless
.ch
)
1906 : XCHAR_TABLE (Vglyphless_char_display
)->extras
[0]);
1907 if (STRINGP (acronym
))
1908 str
= SSDATA (acronym
);
1911 else if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
)
1913 sprintf (buf
, "%0*X",
1914 glyph
->u
.glyphless
.ch
< 0x10000 ? 4 : 6,
1915 glyph
->u
.glyphless
.ch
+ 0u);
1921 int upper_len
= (len
+ 1) / 2;
1924 /* It is assured that all LEN characters in STR is ASCII. */
1925 for (j
= 0; j
< len
; j
++)
1927 code
= s
->font
->driver
->encode_char (s
->font
, str
[j
]);
1928 STORE_XCHAR2B (char2b
+ j
, code
>> 8, code
& 0xFF);
1930 s
->font
->driver
->draw (s
, 0, upper_len
,
1931 x
+ glyph
->slice
.glyphless
.upper_xoff
,
1932 s
->ybase
+ glyph
->slice
.glyphless
.upper_yoff
,
1934 s
->font
->driver
->draw (s
, upper_len
, len
,
1935 x
+ glyph
->slice
.glyphless
.lower_xoff
,
1936 s
->ybase
+ glyph
->slice
.glyphless
.lower_yoff
,
1939 if (glyph
->u
.glyphless
.method
!= GLYPHLESS_DISPLAY_THIN_SPACE
)
1940 x_draw_rectangle (s
->f
, s
->gc
,
1941 x
, s
->ybase
- glyph
->ascent
,
1942 glyph
->pixel_width
- 1,
1943 glyph
->ascent
+ glyph
->descent
- 1);
1944 x
+= glyph
->pixel_width
;
1948 #ifdef USE_X_TOOLKIT
1952 /* Return the frame on which widget WIDGET is used.. Abort if frame
1953 cannot be determined. */
1955 static struct frame
*
1956 x_frame_of_widget (Widget widget
)
1958 struct x_display_info
*dpyinfo
;
1959 Lisp_Object tail
, frame
;
1962 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1964 /* Find the top-level shell of the widget. Note that this function
1965 can be called when the widget is not yet realized, so XtWindow
1966 (widget) == 0. That's the reason we can't simply use
1967 x_any_window_to_frame. */
1968 while (!XtIsTopLevelShell (widget
))
1969 widget
= XtParent (widget
);
1971 /* Look for a frame with that top-level widget. Allocate the color
1972 on that frame to get the right gamma correction value. */
1973 FOR_EACH_FRAME (tail
, frame
)
1977 && f
->output_data
.nothing
!= 1
1978 && FRAME_DISPLAY_INFO (f
) == dpyinfo
1979 && f
->output_data
.x
->widget
== widget
)
1985 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1986 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1987 If this produces the same color as PIXEL, try a color where all RGB
1988 values have DELTA added. Return the allocated color in *PIXEL.
1989 DISPLAY is the X display, CMAP is the colormap to operate on.
1990 Value is true if successful. */
1993 x_alloc_lighter_color_for_widget (Widget widget
, Display
*display
, Colormap cmap
,
1994 unsigned long *pixel
, double factor
, int delta
)
1996 struct frame
*f
= x_frame_of_widget (widget
);
1997 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
2000 #endif /* USE_LUCID */
2003 /* Structure specifying which arguments should be passed by Xt to
2004 cvt_string_to_pixel. We want the widget's screen and colormap. */
2006 static XtConvertArgRec cvt_string_to_pixel_args
[] =
2008 {XtWidgetBaseOffset
, (XtPointer
) offsetof (WidgetRec
, core
.screen
),
2010 {XtWidgetBaseOffset
, (XtPointer
) offsetof (WidgetRec
, core
.colormap
),
2015 /* The address of this variable is returned by
2016 cvt_string_to_pixel. */
2018 static Pixel cvt_string_to_pixel_value
;
2021 /* Convert a color name to a pixel color.
2023 DPY is the display we are working on.
2025 ARGS is an array of *NARGS XrmValue structures holding additional
2026 information about the widget for which the conversion takes place.
2027 The contents of this array are determined by the specification
2028 in cvt_string_to_pixel_args.
2030 FROM is a pointer to an XrmValue which points to the color name to
2031 convert. TO is an XrmValue in which to return the pixel color.
2033 CLOSURE_RET is a pointer to user-data, in which we record if
2034 we allocated the color or not.
2036 Value is True if successful, False otherwise. */
2039 cvt_string_to_pixel (Display
*dpy
, XrmValue
*args
, Cardinal
*nargs
,
2040 XrmValue
*from
, XrmValue
*to
,
2041 XtPointer
*closure_ret
)
2051 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
2052 "wrongParameters", "cvt_string_to_pixel",
2054 "Screen and colormap args required", NULL
, NULL
);
2058 screen
= *(Screen
**) args
[0].addr
;
2059 cmap
= *(Colormap
*) args
[1].addr
;
2060 color_name
= (String
) from
->addr
;
2062 if (strcmp (color_name
, XtDefaultBackground
) == 0)
2064 *closure_ret
= (XtPointer
) False
;
2065 pixel
= WhitePixelOfScreen (screen
);
2067 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
2069 *closure_ret
= (XtPointer
) False
;
2070 pixel
= BlackPixelOfScreen (screen
);
2072 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
2073 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
2075 pixel
= color
.pixel
;
2076 *closure_ret
= (XtPointer
) True
;
2081 Cardinal nparams
= 1;
2083 params
[0] = color_name
;
2084 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
2085 "badValue", "cvt_string_to_pixel",
2086 "XtToolkitError", "Invalid color '%s'",
2091 if (to
->addr
!= NULL
)
2093 if (to
->size
< sizeof (Pixel
))
2095 to
->size
= sizeof (Pixel
);
2099 *(Pixel
*) to
->addr
= pixel
;
2103 cvt_string_to_pixel_value
= pixel
;
2104 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
2107 to
->size
= sizeof (Pixel
);
2112 /* Free a pixel color which was previously allocated via
2113 cvt_string_to_pixel. This is registered as the destructor
2114 for this type of resource via XtSetTypeConverter.
2116 APP is the application context in which we work.
2118 TO is a pointer to an XrmValue holding the color to free.
2119 CLOSURE is the value we stored in CLOSURE_RET for this color
2120 in cvt_string_to_pixel.
2122 ARGS and NARGS are like for cvt_string_to_pixel. */
2125 cvt_pixel_dtor (XtAppContext app
, XrmValuePtr to
, XtPointer closure
, XrmValuePtr args
,
2130 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
2132 "Screen and colormap arguments required",
2135 else if (closure
!= NULL
)
2137 /* We did allocate the pixel, so free it. */
2138 Screen
*screen
= *(Screen
**) args
[0].addr
;
2139 Colormap cmap
= *(Colormap
*) args
[1].addr
;
2140 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
2141 (Pixel
*) to
->addr
, 1);
2146 #endif /* USE_X_TOOLKIT */
2149 /* Value is an array of XColor structures for the contents of the
2150 color map of display DPY. Set *NCELLS to the size of the array.
2151 Note that this probably shouldn't be called for large color maps,
2152 say a 24-bit TrueColor map. */
2154 static const XColor
*
2155 x_color_cells (Display
*dpy
, int *ncells
)
2157 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
2159 if (dpyinfo
->color_cells
== NULL
)
2161 Screen
*screen
= dpyinfo
->screen
;
2162 int ncolor_cells
= XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
2165 dpyinfo
->color_cells
= xnmalloc (ncolor_cells
,
2166 sizeof *dpyinfo
->color_cells
);
2167 dpyinfo
->ncolor_cells
= ncolor_cells
;
2169 for (i
= 0; i
< ncolor_cells
; ++i
)
2170 dpyinfo
->color_cells
[i
].pixel
= i
;
2172 XQueryColors (dpy
, dpyinfo
->cmap
,
2173 dpyinfo
->color_cells
, ncolor_cells
);
2176 *ncells
= dpyinfo
->ncolor_cells
;
2177 return dpyinfo
->color_cells
;
2181 /* On frame F, translate pixel colors to RGB values for the NCOLORS
2182 colors in COLORS. Use cached information, if available. */
2185 x_query_colors (struct frame
*f
, XColor
*colors
, int ncolors
)
2187 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
2189 if (dpyinfo
->red_bits
> 0)
2191 /* For TrueColor displays, we can decompose the RGB value
2194 unsigned int rmult
, gmult
, bmult
;
2195 unsigned int rmask
, gmask
, bmask
;
2197 rmask
= (1 << dpyinfo
->red_bits
) - 1;
2198 gmask
= (1 << dpyinfo
->green_bits
) - 1;
2199 bmask
= (1 << dpyinfo
->blue_bits
) - 1;
2200 /* If we're widening, for example, 8 bits in the pixel value to
2201 16 bits for the separate-color representation, we want to
2202 extrapolate the lower bits based on those bits available --
2203 in other words, we'd like 0xff to become 0xffff instead of
2204 the 0xff00 we'd get by just zero-filling the lower bits.
2206 We generate a 32-bit scaled-up value and shift it, in case
2207 the bit count doesn't divide 16 evenly (e.g., when dealing
2208 with a 3-3-2 bit RGB display), to get more of the lower bits
2211 Should we cache the multipliers in dpyinfo? Maybe
2212 special-case the 8-8-8 common case? */
2213 rmult
= 0xffffffff / rmask
;
2214 gmult
= 0xffffffff / gmask
;
2215 bmult
= 0xffffffff / bmask
;
2217 for (i
= 0; i
< ncolors
; ++i
)
2219 unsigned int r
, g
, b
;
2220 unsigned long pixel
= colors
[i
].pixel
;
2222 r
= (pixel
>> dpyinfo
->red_offset
) & rmask
;
2223 g
= (pixel
>> dpyinfo
->green_offset
) & gmask
;
2224 b
= (pixel
>> dpyinfo
->blue_offset
) & bmask
;
2226 colors
[i
].red
= (r
* rmult
) >> 16;
2227 colors
[i
].green
= (g
* gmult
) >> 16;
2228 colors
[i
].blue
= (b
* bmult
) >> 16;
2233 if (dpyinfo
->color_cells
)
2236 for (i
= 0; i
< ncolors
; ++i
)
2238 unsigned long pixel
= colors
[i
].pixel
;
2239 eassert (pixel
< dpyinfo
->ncolor_cells
);
2240 eassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
2241 colors
[i
] = dpyinfo
->color_cells
[pixel
];
2246 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
2250 /* On frame F, translate pixel color to RGB values for the color in
2251 COLOR. Use cached information, if available. */
2254 x_query_color (struct frame
*f
, XColor
*color
)
2256 x_query_colors (f
, color
, 1);
2260 /* On frame F, translate the color name to RGB values. Use cached
2261 information, if possible.
2263 Note that there is currently no way to clean old entries out of the
2264 cache. However, it is limited to names in the server's database,
2265 and names we've actually looked up; list-colors-display is probably
2266 the most color-intensive case we're likely to hit. */
2268 Status
x_parse_color (struct frame
*f
, const char *color_name
,
2271 Display
*dpy
= FRAME_X_DISPLAY (f
);
2272 Colormap cmap
= FRAME_X_COLORMAP (f
);
2273 struct color_name_cache_entry
*cache_entry
;
2275 if (color_name
[0] == '#')
2277 /* The hex form is parsed directly by XParseColor without
2278 talking to the X server. No need for caching. */
2279 return XParseColor (dpy
, cmap
, color_name
, color
);
2282 for (cache_entry
= FRAME_DISPLAY_INFO (f
)->color_names
; cache_entry
;
2283 cache_entry
= cache_entry
->next
)
2285 if (!xstrcasecmp(cache_entry
->name
, color_name
))
2287 *color
= cache_entry
->rgb
;
2292 if (XParseColor (dpy
, cmap
, color_name
, color
) == 0)
2293 /* No caching of negative results, currently. */
2296 cache_entry
= xzalloc (sizeof *cache_entry
);
2297 cache_entry
->rgb
= *color
;
2298 cache_entry
->name
= xstrdup (color_name
);
2299 cache_entry
->next
= FRAME_DISPLAY_INFO (f
)->color_names
;
2300 FRAME_DISPLAY_INFO (f
)->color_names
= cache_entry
;
2305 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
2306 exact match can't be allocated, try the nearest color available.
2307 Value is true if successful. Set *COLOR to the color
2311 x_alloc_nearest_color_1 (Display
*dpy
, Colormap cmap
, XColor
*color
)
2315 rc
= XAllocColor (dpy
, cmap
, color
) != 0;
2318 /* If we got to this point, the colormap is full, so we're going
2319 to try to get the next closest color. The algorithm used is
2320 a least-squares matching, which is what X uses for closest
2321 color matching with StaticColor visuals. */
2323 int max_color_delta
= 255;
2324 int max_delta
= 3 * max_color_delta
;
2325 int nearest_delta
= max_delta
+ 1;
2327 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
2329 for (nearest
= i
= 0; i
< ncells
; ++i
)
2331 int dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2332 int dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2333 int dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2334 int delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2336 if (delta
< nearest_delta
)
2339 nearest_delta
= delta
;
2343 color
->red
= cells
[nearest
].red
;
2344 color
->green
= cells
[nearest
].green
;
2345 color
->blue
= cells
[nearest
].blue
;
2346 rc
= XAllocColor (dpy
, cmap
, color
) != 0;
2350 /* If allocation succeeded, and the allocated pixel color is not
2351 equal to a cached pixel color recorded earlier, there was a
2352 change in the colormap, so clear the color cache. */
2353 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
2354 XColor
*cached_color
;
2356 if (dpyinfo
->color_cells
2357 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
2358 (cached_color
->red
!= color
->red
2359 || cached_color
->blue
!= color
->blue
2360 || cached_color
->green
!= color
->green
)))
2362 xfree (dpyinfo
->color_cells
);
2363 dpyinfo
->color_cells
= NULL
;
2364 dpyinfo
->ncolor_cells
= 0;
2368 #ifdef DEBUG_X_COLORS
2370 register_color (color
->pixel
);
2371 #endif /* DEBUG_X_COLORS */
2377 /* Allocate the color COLOR->pixel on frame F, colormap CMAP, after
2378 gamma correction. If an exact match can't be allocated, try the
2379 nearest color available. Value is true if successful. Set *COLOR
2380 to the color allocated. */
2383 x_alloc_nearest_color (struct frame
*f
, Colormap cmap
, XColor
*color
)
2385 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
2387 gamma_correct (f
, color
);
2389 if (dpyinfo
->red_bits
> 0)
2391 color
->pixel
= x_make_truecolor_pixel (dpyinfo
,
2398 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
2402 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2403 It's necessary to do this instead of just using PIXEL directly to
2404 get color reference counts right. */
2407 x_copy_color (struct frame
*f
, unsigned long pixel
)
2411 /* If display has an immutable color map, freeing colors is not
2412 necessary and some servers don't allow it. Since we won't free a
2413 color once we've allocated it, we don't need to re-allocate it to
2414 maintain the server's reference count. */
2415 if (!x_mutable_colormap (FRAME_X_VISUAL (f
)))
2418 color
.pixel
= pixel
;
2420 /* The color could still be found in the color_cells array. */
2421 x_query_color (f
, &color
);
2422 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2424 #ifdef DEBUG_X_COLORS
2425 register_color (pixel
);
2431 /* Brightness beyond which a color won't have its highlight brightness
2434 Nominally, highlight colors for `3d' faces are calculated by
2435 brightening an object's color by a constant scale factor, but this
2436 doesn't yield good results for dark colors, so for colors who's
2437 brightness is less than this value (on a scale of 0-65535) have an
2438 use an additional additive factor.
2440 The value here is set so that the default menu-bar/mode-line color
2441 (grey75) will not have its highlights changed at all. */
2442 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
2445 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2446 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2447 If this produces the same color as PIXEL, try a color where all RGB
2448 values have DELTA added. Return the allocated color in *PIXEL.
2449 DISPLAY is the X display, CMAP is the colormap to operate on.
2450 Value is non-zero if successful. */
2453 x_alloc_lighter_color (struct frame
*f
, Display
*display
, Colormap cmap
,
2454 unsigned long *pixel
, double factor
, int delta
)
2460 /* Get RGB color values. */
2461 color
.pixel
= *pixel
;
2462 x_query_color (f
, &color
);
2464 /* Change RGB values by specified FACTOR. Avoid overflow! */
2465 eassert (factor
>= 0);
2466 new.red
= min (0xffff, factor
* color
.red
);
2467 new.green
= min (0xffff, factor
* color
.green
);
2468 new.blue
= min (0xffff, factor
* color
.blue
);
2470 /* Calculate brightness of COLOR. */
2471 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
2473 /* We only boost colors that are darker than
2474 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2475 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2476 /* Make an additive adjustment to NEW, because it's dark enough so
2477 that scaling by FACTOR alone isn't enough. */
2479 /* How far below the limit this color is (0 - 1, 1 being darker). */
2480 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2481 /* The additive adjustment. */
2482 int min_delta
= delta
* dimness
* factor
/ 2;
2486 new.red
= max (0, new.red
- min_delta
);
2487 new.green
= max (0, new.green
- min_delta
);
2488 new.blue
= max (0, new.blue
- min_delta
);
2492 new.red
= min (0xffff, min_delta
+ new.red
);
2493 new.green
= min (0xffff, min_delta
+ new.green
);
2494 new.blue
= min (0xffff, min_delta
+ new.blue
);
2498 /* Try to allocate the color. */
2499 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
2502 if (new.pixel
== *pixel
)
2504 /* If we end up with the same color as before, try adding
2505 delta to the RGB values. */
2506 x_free_colors (f
, &new.pixel
, 1);
2508 new.red
= min (0xffff, delta
+ color
.red
);
2509 new.green
= min (0xffff, delta
+ color
.green
);
2510 new.blue
= min (0xffff, delta
+ color
.blue
);
2511 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
2522 /* Set up the foreground color for drawing relief lines of glyph
2523 string S. RELIEF is a pointer to a struct relief containing the GC
2524 with which lines will be drawn. Use a color that is FACTOR or
2525 DELTA lighter or darker than the relief's background which is found
2526 in S->f->output_data.x->relief_background. If such a color cannot
2527 be allocated, use DEFAULT_PIXEL, instead. */
2530 x_setup_relief_color (struct frame
*f
, struct relief
*relief
, double factor
,
2531 int delta
, unsigned long default_pixel
)
2534 struct x_output
*di
= f
->output_data
.x
;
2535 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
2536 unsigned long pixel
;
2537 unsigned long background
= di
->relief_background
;
2538 Colormap cmap
= FRAME_X_COLORMAP (f
);
2539 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
2540 Display
*dpy
= FRAME_X_DISPLAY (f
);
2542 xgcv
.graphics_exposures
= False
;
2543 xgcv
.line_width
= 1;
2545 /* Free previously allocated color. The color cell will be reused
2546 when it has been freed as many times as it was allocated, so this
2547 doesn't affect faces using the same colors. */
2548 if (relief
->gc
&& relief
->pixel
!= -1)
2550 x_free_colors (f
, &relief
->pixel
, 1);
2554 /* Allocate new color. */
2555 xgcv
.foreground
= default_pixel
;
2557 if (dpyinfo
->n_planes
!= 1
2558 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
2559 xgcv
.foreground
= relief
->pixel
= pixel
;
2561 if (relief
->gc
== 0)
2563 xgcv
.stipple
= dpyinfo
->gray
;
2565 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
2568 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
2572 /* Set up colors for the relief lines around glyph string S. */
2575 x_setup_relief_colors (struct glyph_string
*s
)
2577 struct x_output
*di
= s
->f
->output_data
.x
;
2578 unsigned long color
;
2580 if (s
->face
->use_box_color_for_shadows_p
)
2581 color
= s
->face
->box_color
;
2582 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2584 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2585 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2590 /* Get the background color of the face. */
2591 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2592 color
= xgcv
.background
;
2595 if (di
->white_relief
.gc
== 0
2596 || color
!= di
->relief_background
)
2598 di
->relief_background
= color
;
2599 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2600 WHITE_PIX_DEFAULT (s
->f
));
2601 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2602 BLACK_PIX_DEFAULT (s
->f
));
2607 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2608 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2609 to draw, it must be >= 0. RAISED_P means draw a raised
2610 relief. LEFT_P means draw a relief on the left side of
2611 the rectangle. RIGHT_P means draw a relief on the right
2612 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2616 x_draw_relief_rect (struct frame
*f
,
2617 int left_x
, int top_y
, int right_x
, int bottom_y
,
2618 int width
, bool raised_p
, bool top_p
, bool bot_p
,
2619 bool left_p
, bool right_p
,
2620 XRectangle
*clip_rect
)
2623 GC top_left_gc
, bottom_right_gc
;
2628 top_left_gc
= f
->output_data
.x
->white_relief
.gc
;
2629 bottom_right_gc
= f
->output_data
.x
->black_relief
.gc
;
2633 top_left_gc
= f
->output_data
.x
->black_relief
.gc
;
2634 bottom_right_gc
= f
->output_data
.x
->white_relief
.gc
;
2637 x_set_clip_rectangles (f
, top_left_gc
, clip_rect
, 1);
2638 x_set_clip_rectangles (f
, bottom_right_gc
, clip_rect
, 1);
2642 x_fill_rectangle (f
, top_left_gc
, left_x
, top_y
,
2643 width
, bottom_y
+ 1 - top_y
);
2645 corners
|= 1 << CORNER_TOP_LEFT
;
2647 corners
|= 1 << CORNER_BOTTOM_LEFT
;
2651 x_fill_rectangle (f
, bottom_right_gc
, right_x
+ 1 - width
, top_y
,
2652 width
, bottom_y
+ 1 - top_y
);
2654 corners
|= 1 << CORNER_TOP_RIGHT
;
2656 corners
|= 1 << CORNER_BOTTOM_RIGHT
;
2661 x_fill_rectangle (f
, top_left_gc
, left_x
, top_y
,
2662 right_x
+ 1 - left_x
, width
);
2664 x_fill_trapezoid_for_relief (f
, top_left_gc
, left_x
, top_y
,
2665 right_x
+ 1 - left_x
, width
, 1);
2670 x_fill_rectangle (f
, bottom_right_gc
, left_x
, bottom_y
+ 1 - width
,
2671 right_x
+ 1 - left_x
, width
);
2673 x_fill_trapezoid_for_relief (f
, bottom_right_gc
,
2674 left_x
, bottom_y
+ 1 - width
,
2675 right_x
+ 1 - left_x
, width
, 0);
2677 if (left_p
&& width
!= 1)
2678 x_fill_rectangle (f
, bottom_right_gc
, left_x
, top_y
,
2679 1, bottom_y
+ 1 - top_y
);
2680 if (top_p
&& width
!= 1)
2681 x_fill_rectangle (f
, bottom_right_gc
, left_x
, top_y
,
2682 right_x
+ 1 - left_x
, 1);
2685 XSetBackground (FRAME_X_DISPLAY (f
), top_left_gc
,
2686 FRAME_BACKGROUND_PIXEL (f
));
2687 x_erase_corners_for_relief (f
, top_left_gc
, left_x
, top_y
,
2688 right_x
- left_x
+ 1, bottom_y
- top_y
+ 1,
2692 x_reset_clip_rectangles (f
, top_left_gc
);
2693 x_reset_clip_rectangles (f
, bottom_right_gc
);
2695 Display
*dpy
= FRAME_X_DISPLAY (f
);
2696 Window window
= FRAME_X_WINDOW (f
);
2701 gc
= f
->output_data
.x
->white_relief
.gc
;
2703 gc
= f
->output_data
.x
->black_relief
.gc
;
2704 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2706 /* This code is more complicated than it has to be, because of two
2707 minor hacks to make the boxes look nicer: (i) if width > 1, draw
2708 the outermost line using the black relief. (ii) Omit the four
2715 XDrawLine (dpy
, window
, gc
,
2716 left_x
+ left_p
, top_y
,
2717 right_x
+ !right_p
, top_y
);
2719 for (i
= 1; i
< width
; ++i
)
2720 XDrawLine (dpy
, window
, gc
,
2721 left_x
+ i
* left_p
, top_y
+ i
,
2722 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2729 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
2731 XClearArea (dpy
, window
, left_x
, top_y
, 1, 1, False
);
2732 XClearArea (dpy
, window
, left_x
, bottom_y
, 1, 1, False
);
2734 for (i
= (width
> 1 ? 1 : 0); i
< width
; ++i
)
2735 XDrawLine (dpy
, window
, gc
,
2736 left_x
+ i
, top_y
+ (i
+ 1) * top_p
,
2737 left_x
+ i
, bottom_y
+ 1 - (i
+ 1) * bot_p
);
2740 XSetClipMask (dpy
, gc
, None
);
2742 gc
= f
->output_data
.x
->black_relief
.gc
;
2744 gc
= f
->output_data
.x
->white_relief
.gc
;
2745 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2749 /* Outermost top line. */
2751 XDrawLine (dpy
, window
, gc
,
2752 left_x
+ left_p
, top_y
,
2753 right_x
+ !right_p
, top_y
);
2755 /* Outermost left line. */
2757 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
2763 XDrawLine (dpy
, window
, gc
,
2764 left_x
+ left_p
, bottom_y
,
2765 right_x
+ !right_p
, bottom_y
);
2766 for (i
= 1; i
< width
; ++i
)
2767 XDrawLine (dpy
, window
, gc
,
2768 left_x
+ i
* left_p
, bottom_y
- i
,
2769 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2775 XClearArea (dpy
, window
, right_x
, top_y
, 1, 1, False
);
2776 XClearArea (dpy
, window
, right_x
, bottom_y
, 1, 1, False
);
2777 for (i
= 0; i
< width
; ++i
)
2778 XDrawLine (dpy
, window
, gc
,
2779 right_x
- i
, top_y
+ (i
+ 1) * top_p
,
2780 right_x
- i
, bottom_y
+ 1 - (i
+ 1) * bot_p
);
2783 x_reset_clip_rectangles (f
, gc
);
2789 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2790 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2791 draw, it must be >= 0. LEFT_P means draw a line on the
2792 left side of the rectangle. RIGHT_P means draw a line
2793 on the right side of the rectangle. CLIP_RECT is the clipping
2794 rectangle to use when drawing. */
2797 x_draw_box_rect (struct glyph_string
*s
,
2798 int left_x
, int top_y
, int right_x
, int bottom_y
, int width
,
2799 bool left_p
, bool right_p
, XRectangle
*clip_rect
)
2803 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2804 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2805 x_set_clip_rectangles (s
->f
, s
->gc
, clip_rect
, 1);
2808 x_fill_rectangle (s
->f
, s
->gc
,
2809 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2813 x_fill_rectangle (s
->f
, s
->gc
,
2814 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2817 x_fill_rectangle (s
->f
, s
->gc
,
2818 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2822 x_fill_rectangle (s
->f
, s
->gc
,
2823 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2825 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2826 x_reset_clip_rectangles (s
->f
, s
->gc
);
2830 /* Draw a box around glyph string S. */
2833 x_draw_glyph_string_box (struct glyph_string
*s
)
2835 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
;
2836 bool raised_p
, left_p
, right_p
;
2837 struct glyph
*last_glyph
;
2838 XRectangle clip_rect
;
2840 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2841 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2842 : window_box_right (s
->w
, s
->area
));
2844 /* The glyph that may have a right box line. */
2845 last_glyph
= (s
->cmp
|| s
->img
2847 : s
->first_glyph
+ s
->nchars
- 1);
2849 width
= eabs (s
->face
->box_line_width
);
2850 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2852 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2854 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2856 bottom_y
= top_y
+ s
->height
- 1;
2858 left_p
= (s
->first_glyph
->left_box_line_p
2859 || (s
->hl
== DRAW_MOUSE_FACE
2861 || s
->prev
->hl
!= s
->hl
)));
2862 right_p
= (last_glyph
->right_box_line_p
2863 || (s
->hl
== DRAW_MOUSE_FACE
2865 || s
->next
->hl
!= s
->hl
)));
2867 get_glyph_string_clip_rect (s
, &clip_rect
);
2869 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2870 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2871 left_p
, right_p
, &clip_rect
);
2874 x_setup_relief_colors (s
);
2875 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2876 width
, raised_p
, true, true, left_p
, right_p
,
2882 /* Draw foreground of image glyph string S. */
2885 x_draw_image_foreground (struct glyph_string
*s
)
2888 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2890 /* If first glyph of S has a left box line, start drawing it to the
2891 right of that line. */
2892 if (s
->face
->box
!= FACE_NO_BOX
2893 && s
->first_glyph
->left_box_line_p
2895 x
+= eabs (s
->face
->box_line_width
);
2897 /* If there is a margin around the image, adjust x- and y-position
2899 if (s
->slice
.x
== 0)
2900 x
+= s
->img
->hmargin
;
2901 if (s
->slice
.y
== 0)
2902 y
+= s
->img
->vmargin
;
2908 /* We can't set both a clip mask and use XSetClipRectangles
2909 because the latter also sets a clip mask. We also can't
2910 trust on the shape extension to be available
2911 (XShapeCombineRegion). So, compute the rectangle to draw
2913 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2916 XRectangle clip_rect
, image_rect
, r
;
2918 xgcv
.clip_mask
= s
->img
->mask
;
2919 xgcv
.clip_x_origin
= x
;
2920 xgcv
.clip_y_origin
= y
;
2921 xgcv
.function
= GXcopy
;
2922 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2924 get_glyph_string_clip_rect (s
, &clip_rect
);
2927 image_rect
.width
= s
->slice
.width
;
2928 image_rect
.height
= s
->slice
.height
;
2929 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2930 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2931 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2932 r
.width
, r
.height
, r
.x
, r
.y
);
2936 XRectangle clip_rect
, image_rect
, r
;
2938 get_glyph_string_clip_rect (s
, &clip_rect
);
2941 image_rect
.width
= s
->slice
.width
;
2942 image_rect
.height
= s
->slice
.height
;
2943 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2944 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2945 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2946 r
.width
, r
.height
, r
.x
, r
.y
);
2948 /* When the image has a mask, we can expect that at
2949 least part of a mouse highlight or a block cursor will
2950 be visible. If the image doesn't have a mask, make
2951 a block cursor visible by drawing a rectangle around
2952 the image. I believe it's looking better if we do
2953 nothing here for mouse-face. */
2954 if (s
->hl
== DRAW_CURSOR
)
2956 int relief
= eabs (s
->img
->relief
);
2957 x_draw_rectangle (s
->f
, s
->gc
,
2958 x
- relief
, y
- relief
,
2959 s
->slice
.width
+ relief
*2 - 1,
2960 s
->slice
.height
+ relief
*2 - 1);
2965 /* Draw a rectangle if image could not be loaded. */
2966 x_draw_rectangle (s
->f
, s
->gc
, x
, y
,
2967 s
->slice
.width
- 1, s
->slice
.height
- 1);
2971 /* Draw a relief around the image glyph string S. */
2974 x_draw_image_relief (struct glyph_string
*s
)
2977 bool raised_p
, top_p
, bot_p
, left_p
, right_p
;
2978 int extra_x
, extra_y
;
2981 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2983 /* If first glyph of S has a left box line, start drawing it to the
2984 right of that line. */
2985 if (s
->face
->box
!= FACE_NO_BOX
2986 && s
->first_glyph
->left_box_line_p
2988 x
+= eabs (s
->face
->box_line_width
);
2990 /* If there is a margin around the image, adjust x- and y-position
2992 if (s
->slice
.x
== 0)
2993 x
+= s
->img
->hmargin
;
2994 if (s
->slice
.y
== 0)
2995 y
+= s
->img
->vmargin
;
2997 if (s
->hl
== DRAW_IMAGE_SUNKEN
2998 || s
->hl
== DRAW_IMAGE_RAISED
)
3000 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3001 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3005 thick
= eabs (s
->img
->relief
);
3006 raised_p
= s
->img
->relief
> 0;
3009 x1
= x
+ s
->slice
.width
- 1;
3010 y1
= y
+ s
->slice
.height
- 1;
3012 extra_x
= extra_y
= 0;
3013 if (s
->face
->id
== TOOL_BAR_FACE_ID
)
3015 if (CONSP (Vtool_bar_button_margin
)
3016 && INTEGERP (XCAR (Vtool_bar_button_margin
))
3017 && INTEGERP (XCDR (Vtool_bar_button_margin
)))
3019 extra_x
= XINT (XCAR (Vtool_bar_button_margin
));
3020 extra_y
= XINT (XCDR (Vtool_bar_button_margin
));
3022 else if (INTEGERP (Vtool_bar_button_margin
))
3023 extra_x
= extra_y
= XINT (Vtool_bar_button_margin
);
3026 top_p
= bot_p
= left_p
= right_p
= false;
3028 if (s
->slice
.x
== 0)
3029 x
-= thick
+ extra_x
, left_p
= true;
3030 if (s
->slice
.y
== 0)
3031 y
-= thick
+ extra_y
, top_p
= true;
3032 if (s
->slice
.x
+ s
->slice
.width
== s
->img
->width
)
3033 x1
+= thick
+ extra_x
, right_p
= true;
3034 if (s
->slice
.y
+ s
->slice
.height
== s
->img
->height
)
3035 y1
+= thick
+ extra_y
, bot_p
= true;
3037 x_setup_relief_colors (s
);
3038 get_glyph_string_clip_rect (s
, &r
);
3039 x_draw_relief_rect (s
->f
, x
, y
, x1
, y1
, thick
, raised_p
,
3040 top_p
, bot_p
, left_p
, right_p
, &r
);
3044 /* Draw the foreground of image glyph string S to PIXMAP. */
3047 x_draw_image_foreground_1 (struct glyph_string
*s
, Pixmap pixmap
)
3050 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3052 /* If first glyph of S has a left box line, start drawing it to the
3053 right of that line. */
3054 if (s
->face
->box
!= FACE_NO_BOX
3055 && s
->first_glyph
->left_box_line_p
3057 x
+= eabs (s
->face
->box_line_width
);
3059 /* If there is a margin around the image, adjust x- and y-position
3061 if (s
->slice
.x
== 0)
3062 x
+= s
->img
->hmargin
;
3063 if (s
->slice
.y
== 0)
3064 y
+= s
->img
->vmargin
;
3070 /* We can't set both a clip mask and use XSetClipRectangles
3071 because the latter also sets a clip mask. We also can't
3072 trust on the shape extension to be available
3073 (XShapeCombineRegion). So, compute the rectangle to draw
3075 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3079 xgcv
.clip_mask
= s
->img
->mask
;
3080 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
3081 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
3082 xgcv
.function
= GXcopy
;
3083 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3085 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3086 s
->slice
.x
, s
->slice
.y
,
3087 s
->slice
.width
, s
->slice
.height
, x
, y
);
3088 XSetClipMask (s
->display
, s
->gc
, None
);
3092 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3093 s
->slice
.x
, s
->slice
.y
,
3094 s
->slice
.width
, s
->slice
.height
, x
, y
);
3096 /* When the image has a mask, we can expect that at
3097 least part of a mouse highlight or a block cursor will
3098 be visible. If the image doesn't have a mask, make
3099 a block cursor visible by drawing a rectangle around
3100 the image. I believe it's looking better if we do
3101 nothing here for mouse-face. */
3102 if (s
->hl
== DRAW_CURSOR
)
3104 int r
= eabs (s
->img
->relief
);
3105 x_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3106 s
->slice
.width
+ r
*2 - 1,
3107 s
->slice
.height
+ r
*2 - 1);
3112 /* Draw a rectangle if image could not be loaded. */
3113 x_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3114 s
->slice
.width
- 1, s
->slice
.height
- 1);
3118 /* Draw part of the background of glyph string S. X, Y, W, and H
3119 give the rectangle to draw. */
3122 x_draw_glyph_string_bg_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
3126 /* Fill background with a stipple pattern. */
3127 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3128 x_fill_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
3129 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3132 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3136 /* Draw image glyph string S.
3139 s->x +-------------------------
3142 | +-------------------------
3145 | | +-------------------
3151 x_draw_image_glyph_string (struct glyph_string
*s
)
3153 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
3154 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3156 Pixmap pixmap
= None
;
3159 if (s
->slice
.y
== 0)
3160 height
-= box_line_vwidth
;
3161 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
3162 height
-= box_line_vwidth
;
3164 /* Fill background with face under the image. Do it only if row is
3165 taller than image or if image has a clip mask to reduce
3167 s
->stippled_p
= s
->face
->stipple
!= 0;
3168 if (height
> s
->slice
.height
3172 || s
->img
->pixmap
== 0
3173 || s
->width
!= s
->background_width
)
3177 /* Create a pixmap as large as the glyph string. Fill it
3178 with the background color. Copy the image to it, using
3179 its mask. Copy the temporary pixmap to the display. */
3180 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3181 int depth
= DefaultDepthOfScreen (screen
);
3183 /* Create a pixmap as large as the glyph string. */
3184 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3185 s
->background_width
,
3188 /* Don't clip in the following because we're working on the
3190 XSetClipMask (s
->display
, s
->gc
, None
);
3192 /* Fill the pixmap with the background color/stipple. */
3195 /* Fill background with a stipple pattern. */
3196 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3197 XSetTSOrigin (s
->display
, s
->gc
, - s
->x
, - s
->y
);
3198 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3199 0, 0, s
->background_width
, s
->height
);
3200 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3201 XSetTSOrigin (s
->display
, s
->gc
, 0, 0);
3206 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3208 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3209 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3210 0, 0, s
->background_width
, s
->height
);
3211 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3218 int width
= s
->background_width
;
3220 if (s
->first_glyph
->left_box_line_p
3223 x
+= box_line_hwidth
;
3224 width
-= box_line_hwidth
;
3227 if (s
->slice
.y
== 0)
3228 y
+= box_line_vwidth
;
3230 x_draw_glyph_string_bg_rect (s
, x
, y
, width
, height
);
3233 s
->background_filled_p
= true;
3236 /* Draw the foreground. */
3238 if (s
->img
->cr_data
)
3240 cairo_t
*cr
= x_begin_cr_clip (s
->f
, s
->gc
);
3242 int x
= s
->x
+ s
->img
->hmargin
;
3243 int y
= s
->y
+ s
->img
->vmargin
;
3244 int width
= s
->background_width
;
3246 cairo_set_source_surface (cr
, s
->img
->cr_data
,
3249 cairo_rectangle (cr
, x
, y
, width
, height
);
3251 x_end_cr_clip (s
->f
);
3257 x_draw_image_foreground_1 (s
, pixmap
);
3258 x_set_glyph_string_clipping (s
);
3259 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3260 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3261 XFreePixmap (s
->display
, pixmap
);
3264 x_draw_image_foreground (s
);
3266 /* If we must draw a relief around the image, do it. */
3268 || s
->hl
== DRAW_IMAGE_RAISED
3269 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3270 x_draw_image_relief (s
);
3274 /* Draw stretch glyph string S. */
3277 x_draw_stretch_glyph_string (struct glyph_string
*s
)
3279 eassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3281 if (s
->hl
== DRAW_CURSOR
3282 && !x_stretch_cursor_p
)
3284 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
3285 wide as the stretch glyph. */
3286 int width
, background_width
= s
->background_width
;
3289 if (!s
->row
->reversed_p
)
3291 int left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3295 background_width
-= left_x
- x
;
3301 /* In R2L rows, draw the cursor on the right edge of the
3303 int right_x
= window_box_right (s
->w
, TEXT_AREA
);
3305 if (x
+ background_width
> right_x
)
3306 background_width
-= x
- right_x
;
3307 x
+= background_width
;
3309 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
3310 if (s
->row
->reversed_p
)
3314 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
3316 /* Clear rest using the GC of the original non-cursor face. */
3317 if (width
< background_width
)
3320 int w
= background_width
- width
, h
= s
->height
;
3324 if (!s
->row
->reversed_p
)
3328 if (s
->row
->mouse_face_p
3329 && cursor_in_mouse_face_p (s
->w
))
3331 x_set_mouse_face_gc (s
);
3337 get_glyph_string_clip_rect (s
, &r
);
3338 x_set_clip_rectangles (s
->f
, gc
, &r
, 1);
3340 if (s
->face
->stipple
)
3342 /* Fill background with a stipple pattern. */
3343 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3344 x_fill_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3345 XSetFillStyle (s
->display
, gc
, FillSolid
);
3350 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3351 XSetForeground (s
->display
, gc
, xgcv
.background
);
3352 x_fill_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3353 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3356 x_reset_clip_rectangles (s
->f
, gc
);
3359 else if (!s
->background_filled_p
)
3361 int background_width
= s
->background_width
;
3362 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
3364 /* Don't draw into left margin, fringe or scrollbar area
3365 except for header line and mode line. */
3366 if (x
< left_x
&& !s
->row
->mode_line_p
)
3368 background_width
-= left_x
- x
;
3371 if (background_width
> 0)
3372 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
3375 s
->background_filled_p
= true;
3379 Draw a wavy line under S. The wave fills wave_height pixels from y0.
3385 wave_height = 3 | * * * *
3390 x_draw_underwave (struct glyph_string
*s
)
3392 int wave_height
= 3, wave_length
= 2;
3394 x_draw_horizontal_wave (s
->f
, s
->gc
, s
->x
, s
->ybase
- wave_height
+ 3,
3395 s
->width
, wave_height
, wave_length
);
3396 #else /* not USE_CAIRO */
3397 int dx
, dy
, x0
, y0
, width
, x1
, y1
, x2
, y2
, xmax
;
3399 XRectangle wave_clip
, string_clip
, final_clip
;
3402 dy
= wave_height
- 1;
3404 y0
= s
->ybase
- wave_height
+ 3;
3408 /* Find and set clipping rectangle */
3412 wave_clip
.width
= width
;
3413 wave_clip
.height
= wave_height
;
3414 get_glyph_string_clip_rect (s
, &string_clip
);
3416 if (!x_intersect_rectangles (&wave_clip
, &string_clip
, &final_clip
))
3419 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &final_clip
, 1, Unsorted
);
3421 /* Draw the waves */
3423 x1
= x0
- (x0
% dx
);
3425 odd
= (x1
/ dx
) & 1;
3433 if (INT_MAX
- dx
< xmax
)
3438 XDrawLine (s
->display
, s
->window
, s
->gc
, x1
, y1
, x2
, y2
);
3440 x2
+= dx
, y2
= y0
+ odd
*dy
;
3444 /* Restore previous clipping rectangle(s) */
3445 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, s
->clip
, s
->num_clips
, Unsorted
);
3446 #endif /* not USE_CAIRO */
3450 /* Draw glyph string S. */
3453 x_draw_glyph_string (struct glyph_string
*s
)
3455 bool relief_drawn_p
= false;
3457 /* If S draws into the background of its successors, draw the
3458 background of the successors first so that S can draw into it.
3459 This makes S->next use XDrawString instead of XDrawImageString. */
3460 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
3463 struct glyph_string
*next
;
3465 for (width
= 0, next
= s
->next
;
3466 next
&& width
< s
->right_overhang
;
3467 width
+= next
->width
, next
= next
->next
)
3468 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
3470 x_set_glyph_string_gc (next
);
3471 x_set_glyph_string_clipping (next
);
3472 if (next
->first_glyph
->type
== STRETCH_GLYPH
)
3473 x_draw_stretch_glyph_string (next
);
3475 x_draw_glyph_string_background (next
, true);
3476 next
->num_clips
= 0;
3480 /* Set up S->gc, set clipping and draw S. */
3481 x_set_glyph_string_gc (s
);
3483 /* Draw relief (if any) in advance for char/composition so that the
3484 glyph string can be drawn over it. */
3485 if (!s
->for_overlaps
3486 && s
->face
->box
!= FACE_NO_BOX
3487 && (s
->first_glyph
->type
== CHAR_GLYPH
3488 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3491 x_set_glyph_string_clipping (s
);
3492 x_draw_glyph_string_background (s
, true);
3493 x_draw_glyph_string_box (s
);
3494 x_set_glyph_string_clipping (s
);
3495 relief_drawn_p
= true;
3497 else if (!s
->clip_head
/* draw_glyphs didn't specify a clip mask. */
3499 && ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
3500 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
)))
3501 /* We must clip just this glyph. left_overhang part has already
3502 drawn when s->prev was drawn, and right_overhang part will be
3503 drawn later when s->next is drawn. */
3504 x_set_glyph_string_clipping_exactly (s
, s
);
3506 x_set_glyph_string_clipping (s
);
3508 switch (s
->first_glyph
->type
)
3511 x_draw_image_glyph_string (s
);
3515 x_draw_stretch_glyph_string (s
);
3519 if (s
->for_overlaps
)
3520 s
->background_filled_p
= true;
3522 x_draw_glyph_string_background (s
, false);
3523 x_draw_glyph_string_foreground (s
);
3526 case COMPOSITE_GLYPH
:
3527 if (s
->for_overlaps
|| (s
->cmp_from
> 0
3528 && ! s
->first_glyph
->u
.cmp
.automatic
))
3529 s
->background_filled_p
= true;
3531 x_draw_glyph_string_background (s
, true);
3532 x_draw_composite_glyph_string_foreground (s
);
3535 case GLYPHLESS_GLYPH
:
3536 if (s
->for_overlaps
)
3537 s
->background_filled_p
= true;
3539 x_draw_glyph_string_background (s
, true);
3540 x_draw_glyphless_glyph_string_foreground (s
);
3547 if (!s
->for_overlaps
)
3549 /* Draw underline. */
3550 if (s
->face
->underline_p
)
3552 if (s
->face
->underline_type
== FACE_UNDER_WAVE
)
3554 if (s
->face
->underline_defaulted_p
)
3555 x_draw_underwave (s
);
3559 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3560 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3561 x_draw_underwave (s
);
3562 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3565 else if (s
->face
->underline_type
== FACE_UNDER_LINE
)
3567 unsigned long thickness
, position
;
3570 if (s
->prev
&& s
->prev
->face
->underline_p
3571 && s
->prev
->face
->underline_type
== FACE_UNDER_LINE
)
3573 /* We use the same underline style as the previous one. */
3574 thickness
= s
->prev
->underline_thickness
;
3575 position
= s
->prev
->underline_position
;
3579 /* Get the underline thickness. Default is 1 pixel. */
3580 if (s
->font
&& s
->font
->underline_thickness
> 0)
3581 thickness
= s
->font
->underline_thickness
;
3584 if (x_underline_at_descent_line
)
3585 position
= (s
->height
- thickness
) - (s
->ybase
- s
->y
);
3588 /* Get the underline position. This is the recommended
3589 vertical offset in pixels from the baseline to the top of
3590 the underline. This is a signed value according to the
3591 specs, and its default is
3593 ROUND ((maximum descent) / 2), with
3594 ROUND(x) = floor (x + 0.5) */
3596 if (x_use_underline_position_properties
3597 && s
->font
&& s
->font
->underline_position
>= 0)
3598 position
= s
->font
->underline_position
;
3600 position
= (s
->font
->descent
+ 1) / 2;
3602 position
= underline_minimum_offset
;
3604 position
= max (position
, underline_minimum_offset
);
3606 /* Check the sanity of thickness and position. We should
3607 avoid drawing underline out of the current line area. */
3608 if (s
->y
+ s
->height
<= s
->ybase
+ position
)
3609 position
= (s
->height
- 1) - (s
->ybase
- s
->y
);
3610 if (s
->y
+ s
->height
< s
->ybase
+ position
+ thickness
)
3611 thickness
= (s
->y
+ s
->height
) - (s
->ybase
+ position
);
3612 s
->underline_thickness
= thickness
;
3613 s
->underline_position
= position
;
3614 y
= s
->ybase
+ position
;
3615 if (s
->face
->underline_defaulted_p
)
3616 x_fill_rectangle (s
->f
, s
->gc
,
3617 s
->x
, y
, s
->width
, thickness
);
3621 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3622 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3623 x_fill_rectangle (s
->f
, s
->gc
,
3624 s
->x
, y
, s
->width
, thickness
);
3625 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3629 /* Draw overline. */
3630 if (s
->face
->overline_p
)
3632 unsigned long dy
= 0, h
= 1;
3634 if (s
->face
->overline_color_defaulted_p
)
3635 x_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3640 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3641 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3642 x_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3644 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3648 /* Draw strike-through. */
3649 if (s
->face
->strike_through_p
)
3651 unsigned long h
= 1;
3652 unsigned long dy
= (s
->height
- h
) / 2;
3654 if (s
->face
->strike_through_color_defaulted_p
)
3655 x_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3660 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3661 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3662 x_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3664 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3668 /* Draw relief if not yet drawn. */
3669 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3670 x_draw_glyph_string_box (s
);
3674 struct glyph_string
*prev
;
3676 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
3677 if (prev
->hl
!= s
->hl
3678 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
3680 /* As prev was drawn while clipped to its own area, we
3681 must draw the right_overhang part using s->hl now. */
3682 enum draw_glyphs_face save
= prev
->hl
;
3685 x_set_glyph_string_gc (prev
);
3686 x_set_glyph_string_clipping_exactly (s
, prev
);
3687 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
3688 x_draw_glyph_string_foreground (prev
);
3690 x_draw_composite_glyph_string_foreground (prev
);
3691 x_reset_clip_rectangles (prev
->f
, prev
->gc
);
3693 prev
->num_clips
= 0;
3699 struct glyph_string
*next
;
3701 for (next
= s
->next
; next
; next
= next
->next
)
3702 if (next
->hl
!= s
->hl
3703 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
3705 /* As next will be drawn while clipped to its own area,
3706 we must draw the left_overhang part using s->hl now. */
3707 enum draw_glyphs_face save
= next
->hl
;
3710 x_set_glyph_string_gc (next
);
3711 x_set_glyph_string_clipping_exactly (s
, next
);
3712 if (next
->first_glyph
->type
== CHAR_GLYPH
)
3713 x_draw_glyph_string_foreground (next
);
3715 x_draw_composite_glyph_string_foreground (next
);
3716 x_reset_clip_rectangles (next
->f
, next
->gc
);
3718 next
->num_clips
= 0;
3719 next
->clip_head
= s
->next
;
3724 /* Reset clipping. */
3725 x_reset_clip_rectangles (s
->f
, s
->gc
);
3729 /* Shift display to make room for inserted glyphs. */
3732 x_shift_glyphs_for_insert (struct frame
*f
, int x
, int y
, int width
, int height
, int shift_by
)
3734 /* Never called on a GUI frame, see
3735 http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
3737 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3738 f
->output_data
.x
->normal_gc
,
3739 x
, y
, width
, height
,
3743 /* Delete N glyphs at the nominal cursor position. Not implemented
3747 x_delete_glyphs (struct frame
*f
, register int n
)
3753 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
3754 If they are <= 0, this is probably an error. */
3757 x_clear_area1 (Display
*dpy
, Window window
,
3758 int x
, int y
, int width
, int height
, int exposures
)
3760 eassert (width
> 0 && height
> 0);
3761 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
3766 x_clear_area (struct frame
*f
, int x
, int y
, int width
, int height
)
3771 eassert (width
> 0 && height
> 0);
3773 cr
= x_begin_cr_clip (f
, NULL
);
3774 x_set_cr_source_with_gc_background (f
, f
->output_data
.x
->normal_gc
);
3775 cairo_rectangle (cr
, x
, y
, width
, height
);
3779 x_clear_area1 (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3780 x
, y
, width
, height
, False
);
3785 /* Clear an entire frame. */
3788 x_clear_frame (struct frame
*f
)
3790 /* Clearing the frame will erase any cursor, so mark them all as no
3792 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3798 /* We have to clear the scroll bars. If we have changed colors or
3799 something like that, then they should be notified. */
3800 x_scroll_bar_clear (f
);
3802 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3803 /* Make sure scroll bars are redrawn. As they aren't redrawn by
3804 redisplay, do it here. */
3805 if (FRAME_GTK_WIDGET (f
))
3806 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
3809 XFlush (FRAME_X_DISPLAY (f
));
3814 /* RIF: Show hourglass cursor on frame F. */
3817 x_show_hourglass (struct frame
*f
)
3819 Display
*dpy
= FRAME_X_DISPLAY (f
);
3823 struct x_output
*x
= FRAME_X_OUTPUT (f
);
3824 #ifdef USE_X_TOOLKIT
3827 if (FRAME_OUTER_WINDOW (f
))
3830 x
->hourglass_p
= true;
3832 if (!x
->hourglass_window
)
3834 unsigned long mask
= CWCursor
;
3835 XSetWindowAttributes attrs
;
3837 Window parent
= FRAME_X_WINDOW (f
);
3839 Window parent
= FRAME_OUTER_WINDOW (f
);
3841 attrs
.cursor
= x
->hourglass_cursor
;
3843 x
->hourglass_window
= XCreateWindow
3844 (dpy
, parent
, 0, 0, 32000, 32000, 0, 0,
3845 InputOnly
, CopyFromParent
, mask
, &attrs
);
3848 XMapRaised (dpy
, x
->hourglass_window
);
3854 /* RIF: Cancel hourglass cursor on frame F. */
3857 x_hide_hourglass (struct frame
*f
)
3859 struct x_output
*x
= FRAME_X_OUTPUT (f
);
3861 /* Watch out for newly created frames. */
3862 if (x
->hourglass_window
)
3864 XUnmapWindow (FRAME_X_DISPLAY (f
), x
->hourglass_window
);
3865 /* Sync here because XTread_socket looks at the
3866 hourglass_p flag that is reset to zero below. */
3867 XSync (FRAME_X_DISPLAY (f
), False
);
3868 x
->hourglass_p
= false;
3872 /* Invert the middle quarter of the frame for .15 sec. */
3875 XTflash (struct frame
*f
)
3881 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3882 when the scroll bars and the edit widget share the same X window. */
3883 GdkWindow
*window
= gtk_widget_get_window (FRAME_GTK_WIDGET (f
));
3885 cairo_t
*cr
= gdk_cairo_create (window
);
3886 cairo_set_source_rgb (cr
, 1, 1, 1);
3887 cairo_set_operator (cr
, CAIRO_OPERATOR_DIFFERENCE
);
3888 #define XFillRectangle(d, win, gc, x, y, w, h) \
3890 cairo_rectangle (cr, x, y, w, h); \
3894 #else /* ! HAVE_GTK3 */
3897 vals
.foreground
.pixel
= (FRAME_FOREGROUND_PIXEL (f
)
3898 ^ FRAME_BACKGROUND_PIXEL (f
));
3899 vals
.function
= GDK_XOR
;
3900 gc
= gdk_gc_new_with_values (window
,
3901 &vals
, GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
);
3902 #define XFillRectangle(d, win, gc, x, y, w, h) \
3903 gdk_draw_rectangle (window, gc, true, x, y, w, h)
3904 #endif /* ! HAVE_GTK3 */
3905 #else /* ! USE_GTK */
3908 /* Create a GC that will use the GXxor function to flip foreground
3909 pixels into background pixels. */
3913 values
.function
= GXxor
;
3914 values
.foreground
= (FRAME_FOREGROUND_PIXEL (f
)
3915 ^ FRAME_BACKGROUND_PIXEL (f
));
3917 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3918 GCFunction
| GCForeground
, &values
);
3922 /* Get the height not including a menu bar widget. */
3923 int height
= FRAME_PIXEL_HEIGHT (f
);
3924 /* Height of each line to flash. */
3925 int flash_height
= FRAME_LINE_HEIGHT (f
);
3926 /* These will be the left and right margins of the rectangles. */
3927 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3928 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3929 int width
= flash_right
- flash_left
;
3931 /* If window is tall, flash top and bottom line. */
3932 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3934 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3936 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3937 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3938 width
, flash_height
);
3939 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3941 (height
- flash_height
3942 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3943 width
, flash_height
);
3947 /* If it is short, flash it all. */
3948 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3949 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3950 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3955 struct timespec delay
= make_timespec (0, 150 * 1000 * 1000);
3956 struct timespec wakeup
= timespec_add (current_timespec (), delay
);
3958 /* Keep waiting until past the time wakeup or any input gets
3960 while (! detect_input_pending ())
3962 struct timespec current
= current_timespec ();
3963 struct timespec timeout
;
3965 /* Break if result would not be positive. */
3966 if (timespec_cmp (wakeup
, current
) <= 0)
3969 /* How long `select' should wait. */
3970 timeout
= make_timespec (0, 10 * 1000 * 1000);
3972 /* Try to wait that long--but we might wake up sooner. */
3973 pselect (0, NULL
, NULL
, NULL
, &timeout
, NULL
);
3977 /* If window is tall, flash top and bottom line. */
3978 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3980 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3982 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3983 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3984 width
, flash_height
);
3985 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3987 (height
- flash_height
3988 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3989 width
, flash_height
);
3992 /* If it is short, flash it all. */
3993 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3994 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3995 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4001 g_object_unref (G_OBJECT (gc
));
4003 #undef XFillRectangle
4005 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
4016 XTtoggle_invisible_pointer (struct frame
*f
, bool invisible
)
4019 FRAME_DISPLAY_INFO (f
)->toggle_visible_pointer (f
, invisible
);
4024 /* Make audible bell. */
4027 XTring_bell (struct frame
*f
)
4029 if (FRAME_X_DISPLAY (f
))
4037 XkbBell (FRAME_X_DISPLAY (f
), None
, 0, None
);
4039 XBell (FRAME_X_DISPLAY (f
), 0);
4041 XFlush (FRAME_X_DISPLAY (f
));
4047 /***********************************************************************
4049 ***********************************************************************/
4051 /* Perform an insert-lines or delete-lines operation, inserting N
4052 lines or deleting -N lines at vertical position VPOS. */
4055 x_ins_del_lines (struct frame
*f
, int vpos
, int n
)
4061 /* Scroll part of the display as described by RUN. */
4064 x_scroll_run (struct window
*w
, struct run
*run
)
4066 struct frame
*f
= XFRAME (w
->frame
);
4067 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4069 /* Get frame-relative bounding box of the text display area of W,
4070 without mode lines. Include in this box the left and right
4072 window_box (w
, ANY_AREA
, &x
, &y
, &width
, &height
);
4074 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4075 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4076 bottom_y
= y
+ height
;
4080 /* Scrolling up. Make sure we don't copy part of the mode
4081 line at the bottom. */
4082 if (from_y
+ run
->height
> bottom_y
)
4083 height
= bottom_y
- from_y
;
4085 height
= run
->height
;
4089 /* Scrolling down. Make sure we don't copy over the mode line.
4091 if (to_y
+ run
->height
> bottom_y
)
4092 height
= bottom_y
- to_y
;
4094 height
= run
->height
;
4099 /* Cursor off. Will be switched on again in x_update_window_end. */
4103 SET_FRAME_GARBAGED (f
);
4105 XCopyArea (FRAME_X_DISPLAY (f
),
4106 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4107 f
->output_data
.x
->normal_gc
,
4118 /***********************************************************************
4120 ***********************************************************************/
4124 frame_highlight (struct frame
*f
)
4126 /* We used to only do this if Vx_no_window_manager was non-nil, but
4127 the ICCCM (section 4.1.6) says that the window's border pixmap
4128 and border pixel are window attributes which are "private to the
4129 client", so we can always change it to whatever we want. */
4131 /* I recently started to get errors in this XSetWindowBorder, depending on
4132 the window-manager in use, tho something more is at play since I've been
4133 using that same window-manager binary for ever. Let's not crash just
4134 because of this (bug#9310). */
4135 x_catch_errors (FRAME_X_DISPLAY (f
));
4136 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4137 f
->output_data
.x
->border_pixel
);
4138 x_uncatch_errors ();
4140 x_update_cursor (f
, true);
4141 x_set_frame_alpha (f
);
4145 frame_unhighlight (struct frame
*f
)
4147 /* We used to only do this if Vx_no_window_manager was non-nil, but
4148 the ICCCM (section 4.1.6) says that the window's border pixmap
4149 and border pixel are window attributes which are "private to the
4150 client", so we can always change it to whatever we want. */
4152 /* Same as above for XSetWindowBorder (bug#9310). */
4153 x_catch_errors (FRAME_X_DISPLAY (f
));
4154 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4155 f
->output_data
.x
->border_tile
);
4156 x_uncatch_errors ();
4158 x_update_cursor (f
, true);
4159 x_set_frame_alpha (f
);
4162 /* The focus has changed. Update the frames as necessary to reflect
4163 the new situation. Note that we can't change the selected frame
4164 here, because the Lisp code we are interrupting might become confused.
4165 Each event gets marked with the frame in which it occurred, so the
4166 Lisp code can tell when the switch took place by examining the events. */
4169 x_new_focus_frame (struct x_display_info
*dpyinfo
, struct frame
*frame
)
4171 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
4173 if (frame
!= dpyinfo
->x_focus_frame
)
4175 /* Set this before calling other routines, so that they see
4176 the correct value of x_focus_frame. */
4177 dpyinfo
->x_focus_frame
= frame
;
4179 if (old_focus
&& old_focus
->auto_lower
)
4180 x_lower_frame (old_focus
);
4182 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
4183 dpyinfo
->x_pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
4185 dpyinfo
->x_pending_autoraise_frame
= NULL
;
4188 x_frame_rehighlight (dpyinfo
);
4191 /* Handle FocusIn and FocusOut state changes for FRAME.
4192 If FRAME has focus and there exists more than one frame, puts
4193 a FOCUS_IN_EVENT into *BUFP. */
4196 x_focus_changed (int type
, int state
, struct x_display_info
*dpyinfo
, struct frame
*frame
, struct input_event
*bufp
)
4198 if (type
== FocusIn
)
4200 if (dpyinfo
->x_focus_event_frame
!= frame
)
4202 x_new_focus_frame (dpyinfo
, frame
);
4203 dpyinfo
->x_focus_event_frame
= frame
;
4205 /* Don't stop displaying the initial startup message
4206 for a switch-frame event we don't need. */
4207 /* When run as a daemon, Vterminal_frame is always NIL. */
4208 bufp
->arg
= (((NILP (Vterminal_frame
)
4209 || ! FRAME_X_P (XFRAME (Vterminal_frame
))
4210 || EQ (Fdaemonp (), Qt
))
4211 && CONSP (Vframe_list
)
4212 && !NILP (XCDR (Vframe_list
)))
4214 bufp
->kind
= FOCUS_IN_EVENT
;
4215 XSETFRAME (bufp
->frame_or_window
, frame
);
4218 frame
->output_data
.x
->focus_state
|= state
;
4221 if (FRAME_XIC (frame
))
4222 XSetICFocus (FRAME_XIC (frame
));
4225 else if (type
== FocusOut
)
4227 frame
->output_data
.x
->focus_state
&= ~state
;
4229 if (dpyinfo
->x_focus_event_frame
== frame
)
4231 dpyinfo
->x_focus_event_frame
= 0;
4232 x_new_focus_frame (dpyinfo
, 0);
4234 bufp
->kind
= FOCUS_OUT_EVENT
;
4235 XSETFRAME (bufp
->frame_or_window
, frame
);
4239 if (FRAME_XIC (frame
))
4240 XUnsetICFocus (FRAME_XIC (frame
));
4242 if (frame
->pointer_invisible
)
4243 XTtoggle_invisible_pointer (frame
, false);
4247 /* Return the Emacs frame-object corresponding to an X window.
4248 It could be the frame's main window or an icon window. */
4250 static struct frame
*
4251 x_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
4253 Lisp_Object tail
, frame
;
4259 FOR_EACH_FRAME (tail
, frame
)
4262 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4264 if (f
->output_data
.x
->hourglass_window
== wdesc
)
4266 #ifdef USE_X_TOOLKIT
4267 if ((f
->output_data
.x
->edit_widget
4268 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
4269 /* A tooltip frame? */
4270 || (!f
->output_data
.x
->edit_widget
4271 && FRAME_X_WINDOW (f
) == wdesc
)
4272 || f
->output_data
.x
->icon_desc
== wdesc
)
4274 #else /* not USE_X_TOOLKIT */
4276 if (f
->output_data
.x
->edit_widget
)
4278 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
4279 struct x_output
*x
= f
->output_data
.x
;
4280 if (gwdesc
!= 0 && gwdesc
== x
->edit_widget
)
4283 #endif /* USE_GTK */
4284 if (FRAME_X_WINDOW (f
) == wdesc
4285 || f
->output_data
.x
->icon_desc
== wdesc
)
4287 #endif /* not USE_X_TOOLKIT */
4292 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
4294 /* Like x_window_to_frame but also compares the window with the widget's
4297 static struct frame
*
4298 x_any_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
4300 Lisp_Object tail
, frame
;
4301 struct frame
*f
, *found
= NULL
;
4307 FOR_EACH_FRAME (tail
, frame
)
4312 if (FRAME_X_P (f
) && FRAME_DISPLAY_INFO (f
) == dpyinfo
)
4314 /* This frame matches if the window is any of its widgets. */
4315 x
= f
->output_data
.x
;
4316 if (x
->hourglass_window
== wdesc
)
4321 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
4323 && gtk_widget_get_toplevel (gwdesc
) == x
->widget
)
4326 if (wdesc
== XtWindow (x
->widget
)
4327 || wdesc
== XtWindow (x
->column_widget
)
4328 || wdesc
== XtWindow (x
->edit_widget
))
4330 /* Match if the window is this frame's menubar. */
4331 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
4335 else if (FRAME_X_WINDOW (f
) == wdesc
)
4336 /* A tooltip frame. */
4344 /* Likewise, but consider only the menu bar widget. */
4346 static struct frame
*
4347 x_menubar_window_to_frame (struct x_display_info
*dpyinfo
,
4348 const XEvent
*event
)
4350 Window wdesc
= event
->xany
.window
;
4351 Lisp_Object tail
, frame
;
4358 FOR_EACH_FRAME (tail
, frame
)
4361 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4363 x
= f
->output_data
.x
;
4365 if (x
->menubar_widget
&& xg_event_is_for_menubar (f
, event
))
4368 /* Match if the window is this frame's menubar. */
4369 if (x
->menubar_widget
4370 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
4377 /* Return the frame whose principal (outermost) window is WDESC.
4378 If WDESC is some other (smaller) window, we return 0. */
4381 x_top_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
4383 Lisp_Object tail
, frame
;
4390 FOR_EACH_FRAME (tail
, frame
)
4393 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
4395 x
= f
->output_data
.x
;
4399 /* This frame matches if the window is its topmost widget. */
4401 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
4402 if (gwdesc
== x
->widget
)
4405 if (wdesc
== XtWindow (x
->widget
))
4409 else if (FRAME_X_WINDOW (f
) == wdesc
)
4410 /* Tooltip frame. */
4416 #else /* !USE_X_TOOLKIT && !USE_GTK */
4418 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
4419 #define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
4421 #endif /* USE_X_TOOLKIT || USE_GTK */
4423 /* The focus may have changed. Figure out if it is a real focus change,
4424 by checking both FocusIn/Out and Enter/LeaveNotify events.
4426 Returns FOCUS_IN_EVENT event in *BUFP. */
4429 x_detect_focus_change (struct x_display_info
*dpyinfo
, struct frame
*frame
,
4430 const XEvent
*event
, struct input_event
*bufp
)
4435 switch (event
->type
)
4440 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
4442 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
4444 if (event
->xcrossing
.detail
!= NotifyInferior
4445 && event
->xcrossing
.focus
4446 && ! (focus_state
& FOCUS_EXPLICIT
))
4447 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
4449 dpyinfo
, frame
, bufp
);
4455 x_focus_changed (event
->type
,
4456 (event
->xfocus
.detail
== NotifyPointer
?
4457 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
4458 dpyinfo
, frame
, bufp
);
4462 if (event
->xclient
.message_type
== dpyinfo
->Xatom_XEMBED
)
4464 enum xembed_message msg
= event
->xclient
.data
.l
[1];
4465 x_focus_changed ((msg
== XEMBED_FOCUS_IN
? FocusIn
: FocusOut
),
4466 FOCUS_EXPLICIT
, dpyinfo
, frame
, bufp
);
4473 #if !defined USE_X_TOOLKIT && !defined USE_GTK
4474 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4477 x_mouse_leave (struct x_display_info
*dpyinfo
)
4479 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
4483 /* The focus has changed, or we have redirected a frame's focus to
4484 another frame (this happens when a frame uses a surrogate
4485 mini-buffer frame). Shift the highlight as appropriate.
4487 The FRAME argument doesn't necessarily have anything to do with which
4488 frame is being highlighted or un-highlighted; we only use it to find
4489 the appropriate X display info. */
4492 XTframe_rehighlight (struct frame
*frame
)
4494 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame
));
4498 x_frame_rehighlight (struct x_display_info
*dpyinfo
)
4500 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
4502 if (dpyinfo
->x_focus_frame
)
4504 dpyinfo
->x_highlight_frame
4505 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
4506 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
4507 : dpyinfo
->x_focus_frame
);
4508 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
4510 fset_focus_frame (dpyinfo
->x_focus_frame
, Qnil
);
4511 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
4515 dpyinfo
->x_highlight_frame
= 0;
4517 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
4520 frame_unhighlight (old_highlight
);
4521 if (dpyinfo
->x_highlight_frame
)
4522 frame_highlight (dpyinfo
->x_highlight_frame
);
4528 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
4530 /* Initialize mode_switch_bit and modifier_meaning. */
4532 x_find_modifier_meanings (struct x_display_info
*dpyinfo
)
4534 int min_code
, max_code
;
4537 XModifierKeymap
*mods
;
4539 dpyinfo
->meta_mod_mask
= 0;
4540 dpyinfo
->shift_lock_mask
= 0;
4541 dpyinfo
->alt_mod_mask
= 0;
4542 dpyinfo
->super_mod_mask
= 0;
4543 dpyinfo
->hyper_mod_mask
= 0;
4545 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
4547 syms
= XGetKeyboardMapping (dpyinfo
->display
,
4548 min_code
, max_code
- min_code
+ 1,
4550 mods
= XGetModifierMapping (dpyinfo
->display
);
4552 /* Scan the modifier table to see which modifier bits the Meta and
4553 Alt keysyms are on. */
4555 int row
, col
; /* The row and column in the modifier table. */
4556 bool found_alt_or_meta
;
4558 for (row
= 3; row
< 8; row
++)
4560 found_alt_or_meta
= false;
4561 for (col
= 0; col
< mods
->max_keypermod
; col
++)
4563 KeyCode code
= mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
4565 /* Zeroes are used for filler. Skip them. */
4569 /* Are any of this keycode's keysyms a meta key? */
4573 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
4575 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
4581 found_alt_or_meta
= true;
4582 dpyinfo
->meta_mod_mask
|= (1 << row
);
4587 found_alt_or_meta
= true;
4588 dpyinfo
->alt_mod_mask
|= (1 << row
);
4593 if (!found_alt_or_meta
)
4594 dpyinfo
->hyper_mod_mask
|= (1 << row
);
4595 code_col
= syms_per_code
;
4596 col
= mods
->max_keypermod
;
4601 if (!found_alt_or_meta
)
4602 dpyinfo
->super_mod_mask
|= (1 << row
);
4603 code_col
= syms_per_code
;
4604 col
= mods
->max_keypermod
;
4608 /* Ignore this if it's not on the lock modifier. */
4609 if (!found_alt_or_meta
&& ((1 << row
) == LockMask
))
4610 dpyinfo
->shift_lock_mask
= LockMask
;
4611 code_col
= syms_per_code
;
4612 col
= mods
->max_keypermod
;
4621 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4622 if (! dpyinfo
->meta_mod_mask
)
4624 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4625 dpyinfo
->alt_mod_mask
= 0;
4628 /* If some keys are both alt and meta,
4629 make them just meta, not alt. */
4630 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4632 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4636 XFreeModifiermap (mods
);
4639 /* Convert between the modifier bits X uses and the modifier bits
4643 x_x_to_emacs_modifiers (struct x_display_info
*dpyinfo
, int state
)
4645 int mod_meta
= meta_modifier
;
4646 int mod_alt
= alt_modifier
;
4647 int mod_hyper
= hyper_modifier
;
4648 int mod_super
= super_modifier
;
4651 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
4652 if (INTEGERP (tem
)) mod_alt
= XINT (tem
) & INT_MAX
;
4653 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
4654 if (INTEGERP (tem
)) mod_meta
= XINT (tem
) & INT_MAX
;
4655 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
4656 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
) & INT_MAX
;
4657 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
4658 if (INTEGERP (tem
)) mod_super
= XINT (tem
) & INT_MAX
;
4660 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
4661 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
4662 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
4663 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
4664 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
4665 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
4669 x_emacs_to_x_modifiers (struct x_display_info
*dpyinfo
, EMACS_INT state
)
4671 EMACS_INT mod_meta
= meta_modifier
;
4672 EMACS_INT mod_alt
= alt_modifier
;
4673 EMACS_INT mod_hyper
= hyper_modifier
;
4674 EMACS_INT mod_super
= super_modifier
;
4678 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
4679 if (INTEGERP (tem
)) mod_alt
= XINT (tem
);
4680 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
4681 if (INTEGERP (tem
)) mod_meta
= XINT (tem
);
4682 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
4683 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
);
4684 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
4685 if (INTEGERP (tem
)) mod_super
= XINT (tem
);
4688 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
4689 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
4690 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
4691 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4692 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4693 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
4696 /* Convert a keysym to its name. */
4699 x_get_keysym_name (int keysym
)
4704 value
= XKeysymToString (keysym
);
4710 /* Mouse clicks and mouse movement. Rah.
4712 Formerly, we used PointerMotionHintMask (in standard_event_mask)
4713 so that we would have to call XQueryPointer after each MotionNotify
4714 event to ask for another such event. However, this made mouse tracking
4715 slow, and there was a bug that made it eventually stop.
4717 Simply asking for MotionNotify all the time seems to work better.
4719 In order to avoid asking for motion events and then throwing most
4720 of them away or busy-polling the server for mouse positions, we ask
4721 the server for pointer motion hints. This means that we get only
4722 one event per group of mouse movements. "Groups" are delimited by
4723 other kinds of events (focus changes and button clicks, for
4724 example), or by XQueryPointer calls; when one of these happens, we
4725 get another MotionNotify event the next time the mouse moves. This
4726 is at least as efficient as getting motion events when mouse
4727 tracking is on, and I suspect only negligibly worse when tracking
4730 /* Prepare a mouse-event in *RESULT for placement in the input queue.
4732 If the event is a button press, then note that we have grabbed
4736 construct_mouse_click (struct input_event
*result
,
4737 const XButtonEvent
*event
,
4740 /* Make the event type NO_EVENT; we'll change that when we decide
4742 result
->kind
= MOUSE_CLICK_EVENT
;
4743 result
->code
= event
->button
- Button1
;
4744 result
->timestamp
= event
->time
;
4745 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f
),
4747 | (event
->type
== ButtonRelease
4751 XSETINT (result
->x
, event
->x
);
4752 XSETINT (result
->y
, event
->y
);
4753 XSETFRAME (result
->frame_or_window
, f
);
4758 /* Function to report a mouse movement to the mainstream Emacs code.
4759 The input handler calls this.
4761 We have received a mouse movement event, which is given in *event.
4762 If the mouse is over a different glyph than it was last time, tell
4763 the mainstream emacs code by setting mouse_moved. If not, ask for
4764 another motion event, so we can check again the next time it moves. */
4767 note_mouse_movement (struct frame
*frame
, const XMotionEvent
*event
)
4770 struct x_display_info
*dpyinfo
;
4772 if (!FRAME_X_OUTPUT (frame
))
4775 dpyinfo
= FRAME_DISPLAY_INFO (frame
);
4776 dpyinfo
->last_mouse_movement_time
= event
->time
;
4777 dpyinfo
->last_mouse_motion_frame
= frame
;
4778 dpyinfo
->last_mouse_motion_x
= event
->x
;
4779 dpyinfo
->last_mouse_motion_y
= event
->y
;
4781 if (event
->window
!= FRAME_X_WINDOW (frame
))
4783 frame
->mouse_moved
= true;
4784 dpyinfo
->last_mouse_scroll_bar
= NULL
;
4785 note_mouse_highlight (frame
, -1, -1);
4786 dpyinfo
->last_mouse_glyph_frame
= NULL
;
4791 /* Has the mouse moved off the glyph it was on at the last sighting? */
4792 r
= &dpyinfo
->last_mouse_glyph
;
4793 if (frame
!= dpyinfo
->last_mouse_glyph_frame
4794 || event
->x
< r
->x
|| event
->x
>= r
->x
+ r
->width
4795 || event
->y
< r
->y
|| event
->y
>= r
->y
+ r
->height
)
4797 frame
->mouse_moved
= true;
4798 dpyinfo
->last_mouse_scroll_bar
= NULL
;
4799 note_mouse_highlight (frame
, event
->x
, event
->y
);
4800 /* Remember which glyph we're now on. */
4801 remember_mouse_glyph (frame
, event
->x
, event
->y
, r
);
4802 dpyinfo
->last_mouse_glyph_frame
= frame
;
4809 /* Return the current position of the mouse.
4810 *FP should be a frame which indicates which display to ask about.
4812 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4813 and *PART to the frame, window, and scroll bar part that the mouse
4814 is over. Set *X and *Y to the portion and whole of the mouse's
4815 position on the scroll bar.
4817 If the mouse movement started elsewhere, set *FP to the frame the
4818 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4821 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
4822 was at this position.
4824 Don't store anything if we don't have a valid set of values to report.
4826 This clears the mouse_moved flag, so we can wait for the next mouse
4830 XTmouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
4831 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
4835 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
4839 if (dpyinfo
->last_mouse_scroll_bar
&& insist
== 0)
4841 struct scroll_bar
*bar
= dpyinfo
->last_mouse_scroll_bar
;
4843 if (bar
->horizontal
)
4844 x_horizontal_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, timestamp
);
4846 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, timestamp
);
4853 Window dummy_window
;
4856 Lisp_Object frame
, tail
;
4858 /* Clear the mouse-moved flag for every frame on this display. */
4859 FOR_EACH_FRAME (tail
, frame
)
4860 if (FRAME_X_P (XFRAME (frame
))
4861 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
4862 XFRAME (frame
)->mouse_moved
= false;
4864 dpyinfo
->last_mouse_scroll_bar
= NULL
;
4866 /* Figure out which root window we're on. */
4867 XQueryPointer (FRAME_X_DISPLAY (*fp
),
4868 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
4870 /* The root window which contains the pointer. */
4873 /* Trash which we can't trust if the pointer is on
4874 a different screen. */
4877 /* The position on that root window. */
4880 /* More trash we can't trust. */
4883 /* Modifier keys and pointer buttons, about which
4885 (unsigned int *) &dummy
);
4887 /* Now we have a position on the root; find the innermost window
4888 containing the pointer. */
4892 int parent_x
= 0, parent_y
= 0;
4896 /* XTranslateCoordinates can get errors if the window
4897 structure is changing at the same time this function
4898 is running. So at least we must not crash from them. */
4900 x_catch_errors (FRAME_X_DISPLAY (*fp
));
4902 if (x_mouse_grabbed (dpyinfo
))
4904 /* If mouse was grabbed on a frame, give coords for that frame
4905 even if the mouse is now outside it. */
4906 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4912 FRAME_X_WINDOW (dpyinfo
->last_mouse_frame
),
4914 /* From-position, to-position. */
4915 root_x
, root_y
, &win_x
, &win_y
,
4919 f1
= dpyinfo
->last_mouse_frame
;
4925 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4927 /* From-window, to-window. */
4930 /* From-position, to-position. */
4931 root_x
, root_y
, &win_x
, &win_y
,
4936 if (child
== None
|| child
== win
)
4939 /* We don't wan't to know the innermost window. We
4940 want the edit window. For non-Gtk+ the innermost
4941 window is the edit window. For Gtk+ it might not
4942 be. It might be the tool bar for example. */
4943 if (x_window_to_frame (dpyinfo
, win
))
4951 /* Now we know that:
4952 win is the innermost window containing the pointer
4953 (XTC says it has no child containing the pointer),
4954 win_x and win_y are the pointer's position in it
4955 (XTC did this the last time through), and
4956 parent_x and parent_y are the pointer's position in win's parent.
4957 (They are what win_x and win_y were when win was child.
4958 If win is the root window, it has no parent, and
4959 parent_{x,y} are invalid, but that's okay, because we'll
4960 never use them in that case.) */
4963 /* We don't wan't to know the innermost window. We
4964 want the edit window. */
4965 f1
= x_window_to_frame (dpyinfo
, win
);
4967 /* Is win one of our frames? */
4968 f1
= x_any_window_to_frame (dpyinfo
, win
);
4971 #ifdef USE_X_TOOLKIT
4972 /* If we end up with the menu bar window, say it's not
4975 && f1
->output_data
.x
->menubar_widget
4976 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
4978 #endif /* USE_X_TOOLKIT */
4981 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
4984 x_uncatch_errors_after_check ();
4986 /* If not, is it one of our scroll bars? */
4989 struct scroll_bar
*bar
;
4991 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
, 2);
4995 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5001 if (f1
== 0 && insist
> 0)
5002 f1
= SELECTED_FRAME ();
5006 /* Ok, we found a frame. Store all the values.
5007 last_mouse_glyph is a rectangle used to reduce the
5008 generation of mouse events. To not miss any motion
5009 events, we must divide the frame into rectangles of the
5010 size of the smallest character that could be displayed
5011 on it, i.e. into the same rectangles that matrices on
5012 the frame are divided into. */
5014 /* FIXME: what if F1 is not an X frame? */
5015 dpyinfo
= FRAME_DISPLAY_INFO (f1
);
5016 remember_mouse_glyph (f1
, win_x
, win_y
, &dpyinfo
->last_mouse_glyph
);
5017 dpyinfo
->last_mouse_glyph_frame
= f1
;
5022 XSETINT (*x
, win_x
);
5023 XSETINT (*y
, win_y
);
5024 *timestamp
= dpyinfo
->last_mouse_movement_time
;
5034 /***********************************************************************
5036 ***********************************************************************/
5038 /* Scroll bar support. */
5040 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
5042 This can be called in GC, so we have to make sure to strip off mark
5045 static struct scroll_bar
*
5046 x_window_to_scroll_bar (Display
*display
, Window window_id
, int type
)
5048 Lisp_Object tail
, frame
;
5050 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
5051 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
5052 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
5054 FOR_EACH_FRAME (tail
, frame
)
5056 Lisp_Object bar
, condemned
;
5058 if (! FRAME_X_P (XFRAME (frame
)))
5061 /* Scan this frame's scroll bar list for a scroll bar with the
5063 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
5064 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
5065 /* This trick allows us to search both the ordinary and
5066 condemned scroll bar lists with one loop. */
5067 ! NILP (bar
) || (bar
= condemned
,
5070 bar
= XSCROLL_BAR (bar
)->next
)
5071 if (XSCROLL_BAR (bar
)->x_window
== window_id
5072 && FRAME_X_DISPLAY (XFRAME (frame
)) == display
5074 || (type
== 1 && XSCROLL_BAR (bar
)->horizontal
)
5075 || (type
== 0 && !XSCROLL_BAR (bar
)->horizontal
)))
5076 return XSCROLL_BAR (bar
);
5083 #if defined USE_LUCID
5085 /* Return the Lucid menu bar WINDOW is part of. Return null
5086 if WINDOW is not part of a menu bar. */
5089 x_window_to_menu_bar (Window window
)
5091 Lisp_Object tail
, frame
;
5093 FOR_EACH_FRAME (tail
, frame
)
5094 if (FRAME_X_P (XFRAME (frame
)))
5096 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
5098 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
5104 #endif /* USE_LUCID */
5107 /************************************************************************
5109 ************************************************************************/
5111 #ifdef USE_TOOLKIT_SCROLL_BARS
5113 static void x_send_scroll_bar_event (Lisp_Object
, enum scroll_bar_part
,
5116 /* Lisp window being scrolled. Set when starting to interact with
5117 a toolkit scroll bar, reset to nil when ending the interaction. */
5119 static Lisp_Object window_being_scrolled
;
5121 /* Whether this is an Xaw with arrow-scrollbars. This should imply
5122 that movements of 1/20 of the screen size are mapped to up/down. */
5125 /* Id of action hook installed for scroll bars. */
5127 static XtActionHookId action_hook_id
;
5128 static XtActionHookId horizontal_action_hook_id
;
5130 static Boolean xaw3d_arrow_scroll
;
5132 /* Whether the drag scrolling maintains the mouse at the top of the
5133 thumb. If not, resizing the thumb needs to be done more carefully
5134 to avoid jerkiness. */
5136 static Boolean xaw3d_pick_top
;
5138 /* Action hook installed via XtAppAddActionHook when toolkit scroll
5139 bars are used.. The hook is responsible for detecting when
5140 the user ends an interaction with the scroll bar, and generates
5141 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
5144 xt_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
5145 XEvent
*event
, String
*params
, Cardinal
*num_params
)
5148 const char *end_action
;
5151 scroll_bar_p
= XmIsScrollBar (widget
);
5152 end_action
= "Release";
5153 #else /* !USE_MOTIF i.e. use Xaw */
5154 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
5155 end_action
= "EndScroll";
5156 #endif /* USE_MOTIF */
5159 && strcmp (action_name
, end_action
) == 0
5160 && WINDOWP (window_being_scrolled
))
5163 struct scroll_bar
*bar
;
5165 x_send_scroll_bar_event (window_being_scrolled
,
5166 scroll_bar_end_scroll
, 0, 0, false);
5167 w
= XWINDOW (window_being_scrolled
);
5168 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5170 if (bar
->dragging
!= -1)
5173 /* The thumb size is incorrect while dragging: fix it. */
5174 set_vertical_scroll_bar (w
);
5176 window_being_scrolled
= Qnil
;
5177 #if defined (USE_LUCID)
5178 bar
->last_seen_part
= scroll_bar_nowhere
;
5180 /* Xt timeouts no longer needed. */
5181 toolkit_scroll_bar_interaction
= false;
5187 xt_horizontal_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
5188 XEvent
*event
, String
*params
, Cardinal
*num_params
)
5191 const char *end_action
;
5194 scroll_bar_p
= XmIsScrollBar (widget
);
5195 end_action
= "Release";
5196 #else /* !USE_MOTIF i.e. use Xaw */
5197 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
5198 end_action
= "EndScroll";
5199 #endif /* USE_MOTIF */
5202 && strcmp (action_name
, end_action
) == 0
5203 && WINDOWP (window_being_scrolled
))
5206 struct scroll_bar
*bar
;
5208 x_send_scroll_bar_event (window_being_scrolled
,
5209 scroll_bar_end_scroll
, 0, 0, true);
5210 w
= XWINDOW (window_being_scrolled
);
5211 bar
= XSCROLL_BAR (w
->horizontal_scroll_bar
);
5213 if (bar
->dragging
!= -1)
5216 /* The thumb size is incorrect while dragging: fix it. */
5217 set_horizontal_scroll_bar (w
);
5219 window_being_scrolled
= Qnil
;
5220 #if defined (USE_LUCID)
5221 bar
->last_seen_part
= scroll_bar_nowhere
;
5223 /* Xt timeouts no longer needed. */
5224 toolkit_scroll_bar_interaction
= false;
5227 #endif /* not USE_GTK */
5229 /* Send a client message with message type Xatom_Scrollbar for a
5230 scroll action to the frame of WINDOW. PART is a value identifying
5231 the part of the scroll bar that was clicked on. PORTION is the
5232 amount to scroll of a whole of WHOLE. */
5235 x_send_scroll_bar_event (Lisp_Object window
, enum scroll_bar_part part
,
5236 int portion
, int whole
, bool horizontal
)
5239 XClientMessageEvent
*ev
= &event
.xclient
;
5240 struct window
*w
= XWINDOW (window
);
5241 struct frame
*f
= XFRAME (w
->frame
);
5242 intptr_t iw
= (intptr_t) w
;
5243 enum { BITS_PER_INTPTR
= CHAR_BIT
* sizeof iw
};
5244 verify (BITS_PER_INTPTR
<= 64);
5245 int sign_shift
= BITS_PER_INTPTR
- 32;
5249 /* Construct a ClientMessage event to send to the frame. */
5250 ev
->type
= ClientMessage
;
5251 ev
->message_type
= (horizontal
5252 ? FRAME_DISPLAY_INFO (f
)->Xatom_Horizontal_Scrollbar
5253 : FRAME_DISPLAY_INFO (f
)->Xatom_Scrollbar
);
5254 ev
->display
= FRAME_X_DISPLAY (f
);
5255 ev
->window
= FRAME_X_WINDOW (f
);
5258 /* A 32-bit X client on a 64-bit X server can pass a window pointer
5259 as-is. A 64-bit client on a 32-bit X server is in trouble
5260 because a pointer does not fit and would be truncated while
5261 passing through the server. So use two slots and hope that X12
5262 will resolve such issues someday. */
5263 ev
->data
.l
[0] = iw
>> 31 >> 1;
5264 ev
->data
.l
[1] = sign_shift
<= 0 ? iw
: iw
<< sign_shift
>> sign_shift
;
5265 ev
->data
.l
[2] = part
;
5266 ev
->data
.l
[3] = portion
;
5267 ev
->data
.l
[4] = whole
;
5269 /* Make Xt timeouts work while the scroll bar is active. */
5270 #ifdef USE_X_TOOLKIT
5271 toolkit_scroll_bar_interaction
= true;
5272 x_activate_timeout_atimer ();
5275 /* Setting the event mask to zero means that the message will
5276 be sent to the client that created the window, and if that
5277 window no longer exists, no event will be sent. */
5278 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
5283 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
5287 x_scroll_bar_to_input_event (const XEvent
*event
,
5288 struct input_event
*ievent
)
5290 const XClientMessageEvent
*ev
= &event
->xclient
;
5294 /* See the comment in the function above. */
5295 intptr_t iw0
= ev
->data
.l
[0];
5296 intptr_t iw1
= ev
->data
.l
[1];
5297 intptr_t iw
= (iw0
<< 31 << 1) + (iw1
& 0xffffffffu
);
5298 w
= (struct window
*) iw
;
5300 XSETWINDOW (window
, w
);
5302 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
5303 ievent
->frame_or_window
= window
;
5306 ievent
->timestamp
= CurrentTime
;
5309 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
5312 ievent
->part
= ev
->data
.l
[2];
5313 ievent
->x
= make_number (ev
->data
.l
[3]);
5314 ievent
->y
= make_number (ev
->data
.l
[4]);
5315 ievent
->modifiers
= 0;
5318 /* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
5319 input event in *IEVENT. */
5322 x_horizontal_scroll_bar_to_input_event (const XEvent
*event
,
5323 struct input_event
*ievent
)
5325 const XClientMessageEvent
*ev
= &event
->xclient
;
5329 /* See the comment in the function above. */
5330 intptr_t iw0
= ev
->data
.l
[0];
5331 intptr_t iw1
= ev
->data
.l
[1];
5332 intptr_t iw
= (iw0
<< 31 << 1) + (iw1
& 0xffffffffu
);
5333 w
= (struct window
*) iw
;
5335 XSETWINDOW (window
, w
);
5337 ievent
->kind
= HORIZONTAL_SCROLL_BAR_CLICK_EVENT
;
5338 ievent
->frame_or_window
= window
;
5341 ievent
->timestamp
= CurrentTime
;
5344 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
5347 ievent
->part
= ev
->data
.l
[2];
5348 ievent
->x
= make_number (ev
->data
.l
[3]);
5349 ievent
->y
= make_number (ev
->data
.l
[4]);
5350 ievent
->modifiers
= 0;
5356 /* Minimum and maximum values used for Motif scroll bars. */
5358 #define XM_SB_MAX 10000000
5360 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
5361 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
5362 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
5365 xm_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
5367 struct scroll_bar
*bar
= client_data
;
5368 XmScrollBarCallbackStruct
*cs
= call_data
;
5369 enum scroll_bar_part part
= scroll_bar_nowhere
;
5370 bool horizontal
= bar
->horizontal
;
5371 int whole
= 0, portion
= 0;
5375 case XmCR_DECREMENT
:
5377 part
= horizontal
? scroll_bar_left_arrow
: scroll_bar_up_arrow
;
5380 case XmCR_INCREMENT
:
5382 part
= horizontal
? scroll_bar_right_arrow
: scroll_bar_down_arrow
;
5385 case XmCR_PAGE_DECREMENT
:
5387 part
= horizontal
? scroll_bar_before_handle
: scroll_bar_above_handle
;
5390 case XmCR_PAGE_INCREMENT
:
5392 part
= horizontal
? scroll_bar_after_handle
: scroll_bar_below_handle
;
5397 part
= horizontal
? scroll_bar_to_leftmost
: scroll_bar_to_top
;
5400 case XmCR_TO_BOTTOM
:
5402 part
= horizontal
? scroll_bar_to_rightmost
: scroll_bar_to_bottom
;
5410 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
5415 portion
= bar
->whole
* ((float)cs
->value
/ XM_SB_MAX
);
5416 whole
= bar
->whole
* ((float)(XM_SB_MAX
- slider_size
) / XM_SB_MAX
);
5417 portion
= min (portion
, whole
);
5418 part
= scroll_bar_horizontal_handle
;
5422 whole
= XM_SB_MAX
- slider_size
;
5423 portion
= min (cs
->value
, whole
);
5424 part
= scroll_bar_handle
;
5427 bar
->dragging
= cs
->value
;
5431 case XmCR_VALUE_CHANGED
:
5435 if (part
!= scroll_bar_nowhere
)
5437 window_being_scrolled
= bar
->window
;
5438 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
,
5443 #elif defined USE_GTK
5445 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
5446 bar widget. DATA is a pointer to the scroll_bar structure. */
5449 xg_scroll_callback (GtkRange
*range
,
5450 GtkScrollType scroll
,
5454 int whole
= 0, portion
= 0;
5455 struct scroll_bar
*bar
= user_data
;
5456 enum scroll_bar_part part
= scroll_bar_nowhere
;
5457 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (range
));
5458 struct frame
*f
= g_object_get_data (G_OBJECT (range
), XG_FRAME_DATA
);
5460 if (xg_ignore_gtk_scrollbar
) return false;
5464 case GTK_SCROLL_JUMP
:
5465 /* Buttons 1 2 or 3 must be grabbed. */
5466 if (FRAME_DISPLAY_INFO (f
)->grabbed
!= 0
5467 && FRAME_DISPLAY_INFO (f
)->grabbed
< (1 << 4))
5469 if (bar
->horizontal
)
5471 part
= scroll_bar_horizontal_handle
;
5472 whole
= (int)(gtk_adjustment_get_upper (adj
) -
5473 gtk_adjustment_get_page_size (adj
));
5474 portion
= min ((int)value
, whole
);
5475 bar
->dragging
= portion
;
5479 part
= scroll_bar_handle
;
5480 whole
= gtk_adjustment_get_upper (adj
) -
5481 gtk_adjustment_get_page_size (adj
);
5482 portion
= min ((int)value
, whole
);
5483 bar
->dragging
= portion
;
5487 case GTK_SCROLL_STEP_BACKWARD
:
5488 part
= (bar
->horizontal
5489 ? scroll_bar_left_arrow
: scroll_bar_up_arrow
);
5492 case GTK_SCROLL_STEP_FORWARD
:
5493 part
= (bar
->horizontal
5494 ? scroll_bar_right_arrow
: scroll_bar_down_arrow
);
5497 case GTK_SCROLL_PAGE_BACKWARD
:
5498 part
= (bar
->horizontal
5499 ? scroll_bar_before_handle
: scroll_bar_above_handle
);
5502 case GTK_SCROLL_PAGE_FORWARD
:
5503 part
= (bar
->horizontal
5504 ? scroll_bar_after_handle
: scroll_bar_below_handle
);
5511 if (part
!= scroll_bar_nowhere
)
5513 window_being_scrolled
= bar
->window
;
5514 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
,
5521 /* Callback for button release. Sets dragging to -1 when dragging is done. */
5524 xg_end_scroll_callback (GtkWidget
*widget
,
5525 GdkEventButton
*event
,
5528 struct scroll_bar
*bar
= user_data
;
5530 if (WINDOWP (window_being_scrolled
))
5532 x_send_scroll_bar_event (window_being_scrolled
,
5533 scroll_bar_end_scroll
, 0, 0, bar
->horizontal
);
5534 window_being_scrolled
= Qnil
;
5541 #else /* not USE_GTK and not USE_MOTIF */
5543 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
5544 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
5545 scroll bar struct. CALL_DATA is a pointer to a float saying where
5549 xaw_jump_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
5551 struct scroll_bar
*bar
= client_data
;
5552 float *top_addr
= call_data
;
5553 float top
= *top_addr
;
5555 int whole
, portion
, height
, width
;
5556 enum scroll_bar_part part
;
5557 bool horizontal
= bar
->horizontal
;
5562 /* Get the size of the thumb, a value between 0 and 1. */
5564 XtVaGetValues (widget
, XtNshown
, &shown
, XtNwidth
, &width
, NULL
);
5569 whole
= bar
->whole
- (shown
* bar
->whole
);
5570 portion
= min (top
* bar
->whole
, whole
);
5578 part
= scroll_bar_horizontal_handle
;
5582 /* Get the size of the thumb, a value between 0 and 1. */
5584 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
5588 portion
= shown
< 1 ? top
* whole
: 0;
5590 if (shown
< 1 && (eabs (top
+ shown
- 1) < 1.0f
/ height
))
5591 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
5592 the bottom, so we force the scrolling whenever we see that we're
5593 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
5594 we try to ensure that we always stay two pixels away from the
5596 part
= scroll_bar_down_arrow
;
5598 part
= scroll_bar_handle
;
5601 window_being_scrolled
= bar
->window
;
5602 bar
->dragging
= portion
;
5603 bar
->last_seen_part
= part
;
5604 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
, bar
->horizontal
);
5608 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
5609 i.e. line or page up or down. WIDGET is the Xaw scroll bar
5610 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
5611 the scroll bar. CALL_DATA is an integer specifying the action that
5612 has taken place. Its magnitude is in the range 0..height of the
5613 scroll bar. Negative values mean scroll towards buffer start.
5614 Values < height of scroll bar mean line-wise movement. */
5617 xaw_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
5619 struct scroll_bar
*bar
= client_data
;
5620 /* The position really is stored cast to a pointer. */
5621 int position
= (intptr_t) call_data
;
5622 Dimension height
, width
;
5623 enum scroll_bar_part part
;
5625 if (bar
->horizontal
)
5627 /* Get the width of the scroll bar. */
5629 XtVaGetValues (widget
, XtNwidth
, &width
, NULL
);
5632 if (eabs (position
) >= width
)
5633 part
= (position
< 0) ? scroll_bar_before_handle
: scroll_bar_after_handle
;
5635 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
5636 it maps line-movement to call_data = max(5, height/20). */
5637 else if (xaw3d_arrow_scroll
&& eabs (position
) <= max (5, width
/ 20))
5638 part
= (position
< 0) ? scroll_bar_left_arrow
: scroll_bar_right_arrow
;
5640 part
= scroll_bar_move_ratio
;
5642 window_being_scrolled
= bar
->window
;
5644 bar
->last_seen_part
= part
;
5645 x_send_scroll_bar_event (bar
->window
, part
, position
, width
,
5651 /* Get the height of the scroll bar. */
5653 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
5656 if (eabs (position
) >= height
)
5657 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
5659 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
5660 it maps line-movement to call_data = max(5, height/20). */
5661 else if (xaw3d_arrow_scroll
&& eabs (position
) <= max (5, height
/ 20))
5662 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
5664 part
= scroll_bar_move_ratio
;
5666 window_being_scrolled
= bar
->window
;
5668 bar
->last_seen_part
= part
;
5669 x_send_scroll_bar_event (bar
->window
, part
, position
, height
,
5674 #endif /* not USE_GTK and not USE_MOTIF */
5676 #define SCROLL_BAR_NAME "verticalScrollBar"
5677 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
5679 /* Create the widget for scroll bar BAR on frame F. Record the widget
5680 and X window of the scroll bar in BAR. */
5684 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5686 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
5689 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
5690 G_CALLBACK (xg_end_scroll_callback
),
5696 x_create_horizontal_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5698 const char *scroll_bar_name
= SCROLL_BAR_HORIZONTAL_NAME
;
5701 xg_create_horizontal_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
5702 G_CALLBACK (xg_end_scroll_callback
),
5707 #else /* not USE_GTK */
5710 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5716 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
5717 unsigned long pixel
;
5722 /* Set resources. Create the widget. */
5723 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
5724 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
5725 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
5726 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
5727 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
5728 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
5729 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
5731 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
5734 XtSetArg (av
[ac
], XmNforeground
, pixel
);
5738 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5741 XtSetArg (av
[ac
], XmNbackground
, pixel
);
5745 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
5746 (char *) scroll_bar_name
, av
, ac
);
5748 /* Add one callback for everything that can happen. */
5749 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
5751 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
5753 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
5755 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
5757 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
5759 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
5761 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
5764 /* Realize the widget. Only after that is the X window created. */
5765 XtRealizeWidget (widget
);
5767 /* Set the cursor to an arrow. I didn't find a resource to do that.
5768 And I'm wondering why it hasn't an arrow cursor by default. */
5769 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
5770 f
->output_data
.x
->nontext_cursor
);
5772 #else /* !USE_MOTIF i.e. use Xaw */
5774 /* Set resources. Create the widget. The background of the
5775 Xaw3d scroll bar widget is a little bit light for my taste.
5776 We don't alter it here to let users change it according
5777 to their taste with `emacs*verticalScrollBar.background: xxx'. */
5778 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
5779 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
5780 /* For smoother scrolling with Xaw3d -sm */
5781 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
5783 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
5786 XtSetArg (av
[ac
], XtNforeground
, pixel
);
5790 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5793 XtSetArg (av
[ac
], XtNbackground
, pixel
);
5797 /* Top/bottom shadow colors. */
5799 /* Allocate them, if necessary. */
5800 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
5802 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5805 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
5806 FRAME_X_COLORMAP (f
),
5807 &pixel
, 1.2, 0x8000))
5809 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
5812 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
5814 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5817 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
5818 FRAME_X_COLORMAP (f
),
5819 &pixel
, 0.6, 0x4000))
5821 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
5825 #ifdef XtNbeNiceToColormap
5826 /* Tell the toolkit about them. */
5827 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
5828 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
5829 /* We tried to allocate a color for the top/bottom shadow, and
5830 failed, so tell Xaw3d to use dithering instead. */
5831 /* But only if we have a small colormap. Xaw3d can allocate nice
5834 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
5835 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
5839 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
5840 be more consistent with other emacs 3d colors, and since Xaw3d is
5841 not good at dealing with allocation failure. */
5843 /* This tells Xaw3d to use real colors instead of dithering for
5845 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
5848 /* Specify the colors. */
5849 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
5852 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
5855 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
5858 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
5864 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
5865 f
->output_data
.x
->edit_widget
, av
, ac
);
5868 char const *initial
= "";
5869 char const *val
= initial
;
5870 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
5871 #ifdef XtNarrowScrollbars
5872 XtNarrowScrollbars
, (XtPointer
) &xaw3d_arrow_scroll
,
5874 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
5875 if (xaw3d_arrow_scroll
|| val
== initial
)
5876 { /* ARROW_SCROLL */
5877 xaw3d_arrow_scroll
= True
;
5878 /* Isn't that just a personal preference ? --Stef */
5879 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
5883 /* Define callbacks. */
5884 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
5885 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
5888 /* Realize the widget. Only after that is the X window created. */
5889 XtRealizeWidget (widget
);
5891 #endif /* !USE_MOTIF */
5893 /* Install an action hook that lets us detect when the user
5894 finishes interacting with a scroll bar. */
5895 if (action_hook_id
== 0)
5896 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
5898 /* Remember X window and widget in the scroll bar vector. */
5899 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
5900 xwindow
= XtWindow (widget
);
5901 bar
->x_window
= xwindow
;
5903 bar
->horizontal
= false;
5909 x_create_horizontal_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
5915 const char *scroll_bar_name
= SCROLL_BAR_HORIZONTAL_NAME
;
5916 unsigned long pixel
;
5921 /* Set resources. Create the widget. */
5922 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
5923 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
5924 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
5925 XtSetArg (av
[ac
], XmNorientation
, XmHORIZONTAL
); ++ac
;
5926 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_RIGHT
), ++ac
;
5927 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
5928 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
5930 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
5933 XtSetArg (av
[ac
], XmNforeground
, pixel
);
5937 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5940 XtSetArg (av
[ac
], XmNbackground
, pixel
);
5944 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
5945 (char *) scroll_bar_name
, av
, ac
);
5947 /* Add one callback for everything that can happen. */
5948 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
5950 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
5952 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
5954 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
5956 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
5958 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
5960 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
5963 /* Realize the widget. Only after that is the X window created. */
5964 XtRealizeWidget (widget
);
5966 /* Set the cursor to an arrow. I didn't find a resource to do that.
5967 And I'm wondering why it hasn't an arrow cursor by default. */
5968 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
5969 f
->output_data
.x
->nontext_cursor
);
5971 #else /* !USE_MOTIF i.e. use Xaw */
5973 /* Set resources. Create the widget. The background of the
5974 Xaw3d scroll bar widget is a little bit light for my taste.
5975 We don't alter it here to let users change it according
5976 to their taste with `emacs*verticalScrollBar.background: xxx'. */
5977 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
5978 XtSetArg (av
[ac
], XtNorientation
, XtorientHorizontal
); ++ac
;
5979 /* For smoother scrolling with Xaw3d -sm */
5980 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
5982 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
5985 XtSetArg (av
[ac
], XtNforeground
, pixel
);
5989 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5992 XtSetArg (av
[ac
], XtNbackground
, pixel
);
5996 /* Top/bottom shadow colors. */
5998 /* Allocate them, if necessary. */
5999 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
6001 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
6004 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
6005 FRAME_X_COLORMAP (f
),
6006 &pixel
, 1.2, 0x8000))
6008 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
6011 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
6013 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
6016 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
6017 FRAME_X_COLORMAP (f
),
6018 &pixel
, 0.6, 0x4000))
6020 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
6024 #ifdef XtNbeNiceToColormap
6025 /* Tell the toolkit about them. */
6026 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
6027 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
6028 /* We tried to allocate a color for the top/bottom shadow, and
6029 failed, so tell Xaw3d to use dithering instead. */
6030 /* But only if we have a small colormap. Xaw3d can allocate nice
6033 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
6034 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
6038 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
6039 be more consistent with other emacs 3d colors, and since Xaw3d is
6040 not good at dealing with allocation failure. */
6042 /* This tells Xaw3d to use real colors instead of dithering for
6044 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
6047 /* Specify the colors. */
6048 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
6051 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
6054 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
6057 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
6063 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
6064 f
->output_data
.x
->edit_widget
, av
, ac
);
6067 char const *initial
= "";
6068 char const *val
= initial
;
6069 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
6070 #ifdef XtNarrowScrollbars
6071 XtNarrowScrollbars
, (XtPointer
) &xaw3d_arrow_scroll
,
6073 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
6074 if (xaw3d_arrow_scroll
|| val
== initial
)
6075 { /* ARROW_SCROLL */
6076 xaw3d_arrow_scroll
= True
;
6077 /* Isn't that just a personal preference ? --Stef */
6078 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
6082 /* Define callbacks. */
6083 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
6084 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
6087 /* Realize the widget. Only after that is the X window created. */
6088 XtRealizeWidget (widget
);
6090 #endif /* !USE_MOTIF */
6092 /* Install an action hook that lets us detect when the user
6093 finishes interacting with a scroll bar. */
6094 if (horizontal_action_hook_id
== 0)
6095 horizontal_action_hook_id
6096 = XtAppAddActionHook (Xt_app_con
, xt_horizontal_action_hook
, 0);
6098 /* Remember X window and widget in the scroll bar vector. */
6099 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
6100 xwindow
= XtWindow (widget
);
6101 bar
->x_window
= xwindow
;
6103 bar
->horizontal
= true;
6107 #endif /* not USE_GTK */
6110 /* Set the thumb size and position of scroll bar BAR. We are currently
6111 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6115 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
, int whole
)
6117 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
6121 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
, int whole
)
6123 xg_set_toolkit_horizontal_scroll_bar_thumb (bar
, portion
, position
, whole
);
6126 #else /* not USE_GTK */
6128 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
6131 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6132 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
6139 if (scroll_bar_adjust_thumb_portion_p
)
6141 /* We use an estimate of 30 chars per line rather than the real
6142 `portion' value. This has the disadvantage that the thumb size
6143 is not very representative, but it makes our life a lot easier.
6144 Otherwise, we have to constantly adjust the thumb size, which
6145 we can't always do quickly enough: while dragging, the size of
6146 the thumb might prevent the user from dragging the thumb all the
6147 way to the end. but Motif and some versions of Xaw3d don't allow
6148 updating the thumb size while dragging. Also, even if we can update
6149 its size, the update will often happen too late.
6150 If you don't believe it, check out revision 1.650 of xterm.c to see
6151 what hoops we were going through and the still poor behavior we got. */
6152 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
6153 /* When the thumb is at the bottom, position == whole.
6154 So we need to increase `whole' to make space for the thumb. */
6162 top
= (float) position
/ whole
;
6163 shown
= (float) portion
/ whole
;
6166 if (bar
->dragging
== -1)
6170 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
6171 is the scroll bar's maximum and MIN is the scroll bar's minimum
6173 size
= clip_to_bounds (1, shown
* XM_SB_MAX
, XM_SB_MAX
);
6175 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
6176 value
= top
* XM_SB_MAX
;
6177 value
= min (value
, XM_SB_MAX
- size
);
6179 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
6181 #else /* !USE_MOTIF i.e. use Xaw */
6187 top
= (float) position
/ whole
;
6188 shown
= (float) portion
/ whole
;
6192 float old_top
, old_shown
;
6194 XtVaGetValues (widget
,
6195 XtNtopOfThumb
, &old_top
,
6196 XtNshown
, &old_shown
,
6200 /* Massage the top+shown values. */
6201 if (bar
->dragging
== -1 || bar
->last_seen_part
== scroll_bar_down_arrow
)
6202 top
= max (0, min (1, top
));
6205 #if ! defined (HAVE_XAW3D)
6206 /* With Xaw, 'top' values too closer to 1.0 may
6207 cause the thumb to disappear. Fix that. */
6208 top
= min (top
, 0.99f
);
6210 /* Keep two pixels available for moving the thumb down. */
6211 shown
= max (0, min (1 - top
- (2.0f
/ height
), shown
));
6212 #if ! defined (HAVE_XAW3D)
6213 /* Likewise with too small 'shown'. */
6214 shown
= max (shown
, 0.01f
);
6217 /* If the call to XawScrollbarSetThumb below doesn't seem to
6218 work, check that 'NARROWPROTO' is defined in src/config.h.
6219 If this is not so, most likely you need to fix configure. */
6220 if (top
!= old_top
|| shown
!= old_shown
)
6222 if (bar
->dragging
== -1)
6223 XawScrollbarSetThumb (widget
, top
, shown
);
6226 /* Try to make the scrolling a tad smoother. */
6227 if (!xaw3d_pick_top
)
6228 shown
= min (shown
, old_shown
);
6230 XawScrollbarSetThumb (widget
, top
, shown
);
6234 #endif /* !USE_MOTIF */
6240 x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
6243 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6244 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
6251 shown
= (float) portion
/ whole
;
6252 top
= (float) position
/ (whole
- portion
);
6254 int size
= clip_to_bounds (1, shown
* XM_SB_MAX
, XM_SB_MAX
);
6255 int value
= clip_to_bounds (0, top
* (XM_SB_MAX
- size
), XM_SB_MAX
- size
);
6257 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
6259 #else /* !USE_MOTIF i.e. use Xaw */
6265 top
= (float) position
/ whole
;
6266 shown
= (float) portion
/ whole
;
6270 float old_top
, old_shown
;
6272 XtVaGetValues (widget
,
6273 XtNtopOfThumb
, &old_top
,
6274 XtNshown
, &old_shown
,
6279 /* Massage the top+shown values. */
6280 if (bar
->dragging
== -1 || bar
->last_seen_part
== scroll_bar_down_arrow
)
6281 top
= max (0, min (1, top
));
6284 #if ! defined (HAVE_XAW3D)
6285 /* With Xaw, 'top' values too closer to 1.0 may
6286 cause the thumb to disappear. Fix that. */
6287 top
= min (top
, 0.99f
);
6289 /* Keep two pixels available for moving the thumb down. */
6290 shown
= max (0, min (1 - top
- (2.0f
/ height
), shown
));
6291 #if ! defined (HAVE_XAW3D)
6292 /* Likewise with too small 'shown'. */
6293 shown
= max (shown
, 0.01f
);
6297 /* If the call to XawScrollbarSetThumb below doesn't seem to
6298 work, check that 'NARROWPROTO' is defined in src/config.h.
6299 If this is not so, most likely you need to fix configure. */
6300 XawScrollbarSetThumb (widget
, top
, shown
);
6302 if (top
!= old_top
|| shown
!= old_shown
)
6304 if (bar
->dragging
== -1)
6305 XawScrollbarSetThumb (widget
, top
, shown
);
6308 /* Try to make the scrolling a tad smoother. */
6309 if (!xaw3d_pick_top
)
6310 shown
= min (shown
, old_shown
);
6312 XawScrollbarSetThumb (widget
, top
, shown
);
6317 #endif /* !USE_MOTIF */
6321 #endif /* not USE_GTK */
6323 #endif /* USE_TOOLKIT_SCROLL_BARS */
6327 /************************************************************************
6328 Scroll bars, general
6329 ************************************************************************/
6331 /* Create a scroll bar and return the scroll bar vector for it. W is
6332 the Emacs window on which to create the scroll bar. TOP, LEFT,
6333 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
6336 static struct scroll_bar
*
6337 x_scroll_bar_create (struct window
*w
, int top
, int left
,
6338 int width
, int height
, bool horizontal
)
6340 struct frame
*f
= XFRAME (w
->frame
);
6341 struct scroll_bar
*bar
6342 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar
, x_window
, PVEC_OTHER
);
6347 #ifdef USE_TOOLKIT_SCROLL_BARS
6349 x_create_horizontal_toolkit_scroll_bar (f
, bar
);
6351 x_create_toolkit_scroll_bar (f
, bar
);
6352 #else /* not USE_TOOLKIT_SCROLL_BARS */
6354 XSetWindowAttributes a
;
6358 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
6359 if (a
.background_pixel
== -1)
6360 a
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
6362 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
6363 | ButtonMotionMask
| PointerMotionHintMask
6365 a
.cursor
= FRAME_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
6367 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
6369 /* Clear the area of W that will serve as a scroll bar. This is
6370 for the case that a window has been split horizontally. In
6371 this case, no clear_frame is generated to reduce flickering. */
6372 if (width
> 0 && window_box_height (w
) > 0)
6373 x_clear_area (f
, left
, top
, width
, window_box_height (w
));
6375 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6376 /* Position and size of scroll bar. */
6377 left
, top
, width
, height
,
6378 /* Border width, depth, class, and visual. */
6385 bar
->x_window
= window
;
6387 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6389 XSETWINDOW (bar
->window
, w
);
6393 bar
->height
= height
;
6397 bar
->horizontal
= horizontal
;
6398 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
6399 bar
->last_seen_part
= scroll_bar_nowhere
;
6402 /* Add bar to its frame's list of scroll bars. */
6403 bar
->next
= FRAME_SCROLL_BARS (f
);
6405 XSETVECTOR (barobj
, bar
);
6406 fset_scroll_bars (f
, barobj
);
6407 if (!NILP (bar
->next
))
6408 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
6410 /* Map the window/widget. */
6411 #ifdef USE_TOOLKIT_SCROLL_BARS
6415 xg_update_horizontal_scrollbar_pos (f
, bar
->x_window
, top
,
6416 left
, width
, max (height
, 1));
6418 xg_update_scrollbar_pos (f
, bar
->x_window
, top
,
6419 left
, width
, max (height
, 1));
6420 #else /* not USE_GTK */
6421 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
6422 XtConfigureWidget (scroll_bar
, left
, top
, width
, max (height
, 1), 0);
6423 XtMapWidget (scroll_bar
);
6424 #endif /* not USE_GTK */
6426 #else /* not USE_TOOLKIT_SCROLL_BARS */
6427 XMapRaised (FRAME_X_DISPLAY (f
), bar
->x_window
);
6428 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6435 #ifndef USE_TOOLKIT_SCROLL_BARS
6437 /* Draw BAR's handle in the proper position.
6439 If the handle is already drawn from START to END, don't bother
6440 redrawing it, unless REBUILD; in that case, always
6441 redraw it. (REBUILD is handy for drawing the handle after expose
6444 Normally, we want to constrain the start and end of the handle to
6445 fit inside its rectangle, but if the user is dragging the scroll
6446 bar handle, we want to let them drag it down all the way, so that
6447 the bar's top is as far down as it goes; otherwise, there's no way
6448 to move to the very end of the buffer. */
6451 x_scroll_bar_set_handle (struct scroll_bar
*bar
, int start
, int end
,
6454 bool dragging
= bar
->dragging
!= -1;
6455 Window w
= bar
->x_window
;
6456 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6457 GC gc
= f
->output_data
.x
->normal_gc
;
6459 /* If the display is already accurate, do nothing. */
6461 && start
== bar
->start
6468 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, bar
->width
);
6469 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, bar
->height
);
6470 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
6472 /* Make sure the values are reasonable, and try to preserve
6473 the distance between start and end. */
6475 int length
= end
- start
;
6479 else if (start
> top_range
)
6481 end
= start
+ length
;
6485 else if (end
> top_range
&& ! dragging
)
6489 /* Store the adjusted setting in the scroll bar. */
6493 /* Clip the end position, just for display. */
6494 if (end
> top_range
)
6497 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
6498 below top positions, to make sure the handle is always at least
6499 that many pixels tall. */
6500 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
6502 /* Draw the empty space above the handle. Note that we can't clear
6503 zero-height areas; that means "clear to end of window." */
6504 if ((inside_width
> 0) && (start
> 0))
6505 x_clear_area1 (FRAME_X_DISPLAY (f
), w
,
6506 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
6507 VERTICAL_SCROLL_BAR_TOP_BORDER
,
6508 inside_width
, start
, False
);
6510 /* Change to proper foreground color if one is specified. */
6511 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
6512 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
6513 f
->output_data
.x
->scroll_bar_foreground_pixel
);
6515 /* Draw the handle itself. */
6516 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
6517 /* x, y, width, height */
6518 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
6519 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
6520 inside_width
, end
- start
);
6522 /* Restore the foreground color of the GC if we changed it above. */
6523 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
6524 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
6525 FRAME_FOREGROUND_PIXEL (f
));
6527 /* Draw the empty space below the handle. Note that we can't
6528 clear zero-height areas; that means "clear to end of window." */
6529 if ((inside_width
> 0) && (end
< inside_height
))
6530 x_clear_area1 (FRAME_X_DISPLAY (f
), w
,
6531 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
6532 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
6533 inside_width
, inside_height
- end
, False
);
6539 #endif /* !USE_TOOLKIT_SCROLL_BARS */
6541 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6545 x_scroll_bar_remove (struct scroll_bar
*bar
)
6547 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6550 #ifdef USE_TOOLKIT_SCROLL_BARS
6552 xg_remove_scroll_bar (f
, bar
->x_window
);
6553 #else /* not USE_GTK */
6554 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
6555 #endif /* not USE_GTK */
6557 XDestroyWindow (FRAME_X_DISPLAY (f
), bar
->x_window
);
6560 /* Dissociate this scroll bar from its window. */
6561 if (bar
->horizontal
)
6562 wset_horizontal_scroll_bar (XWINDOW (bar
->window
), Qnil
);
6564 wset_vertical_scroll_bar (XWINDOW (bar
->window
), Qnil
);
6570 /* Set the handle of the vertical scroll bar for WINDOW to indicate
6571 that we are displaying PORTION characters out of a total of WHOLE
6572 characters, starting at POSITION. If WINDOW has no scroll bar,
6576 XTset_vertical_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
6578 struct frame
*f
= XFRAME (w
->frame
);
6580 struct scroll_bar
*bar
;
6581 int top
, height
, left
, width
;
6582 int window_y
, window_height
;
6584 /* Get window dimensions. */
6585 window_box (w
, ANY_AREA
, 0, &window_y
, 0, &window_height
);
6587 height
= window_height
;
6588 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
6589 width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
6591 /* Does the scroll bar exist yet? */
6592 if (NILP (w
->vertical_scroll_bar
))
6594 if (width
> 0 && height
> 0)
6597 x_clear_area (f
, left
, top
, width
, height
);
6601 bar
= x_scroll_bar_create (w
, top
, left
, width
, max (height
, 1), false);
6605 /* It may just need to be moved and resized. */
6606 unsigned int mask
= 0;
6608 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
6612 if (left
!= bar
->left
)
6614 if (top
!= bar
->top
)
6616 if (width
!= bar
->width
)
6618 if (height
!= bar
->height
)
6621 #ifdef USE_TOOLKIT_SCROLL_BARS
6623 /* Move/size the scroll bar widget. */
6626 /* Since toolkit scroll bars are smaller than the space reserved
6627 for them on the frame, we have to clear "under" them. */
6628 if (width
> 0 && height
> 0)
6629 x_clear_area (f
, left
, top
, width
, height
);
6631 xg_update_scrollbar_pos (f
, bar
->x_window
, top
,
6632 left
, width
, max (height
, 1));
6633 #else /* not USE_GTK */
6634 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
6635 left
, top
, width
, max (height
, 1), 0);
6636 #endif /* not USE_GTK */
6638 #else /* not USE_TOOLKIT_SCROLL_BARS */
6640 /* Move/size the scroll bar window. */
6649 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
6653 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6655 /* Remember new settings. */
6659 bar
->height
= height
;
6664 #ifdef USE_TOOLKIT_SCROLL_BARS
6665 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
6666 #else /* not USE_TOOLKIT_SCROLL_BARS */
6667 /* Set the scroll bar's current state, unless we're currently being
6669 if (bar
->dragging
== -1)
6671 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
6674 x_scroll_bar_set_handle (bar
, 0, top_range
, false);
6677 int start
= ((double) position
* top_range
) / whole
;
6678 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
6679 x_scroll_bar_set_handle (bar
, start
, end
, false);
6682 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6684 XSETVECTOR (barobj
, bar
);
6685 wset_vertical_scroll_bar (w
, barobj
);
6690 XTset_horizontal_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
6692 struct frame
*f
= XFRAME (w
->frame
);
6694 struct scroll_bar
*bar
;
6695 int top
, height
, left
, width
;
6696 int window_x
, window_width
;
6697 int pixel_width
= WINDOW_PIXEL_WIDTH (w
);
6699 /* Get window dimensions. */
6700 window_box (w
, ANY_AREA
, &window_x
, 0, &window_width
, 0);
6702 width
= window_width
;
6703 top
= WINDOW_SCROLL_BAR_AREA_Y (w
);
6704 height
= WINDOW_SCROLL_BAR_AREA_HEIGHT (w
);
6706 /* Does the scroll bar exist yet? */
6707 if (NILP (w
->horizontal_scroll_bar
))
6709 if (width
> 0 && height
> 0)
6713 /* Clear also part between window_width and
6714 WINDOW_PIXEL_WIDTH. */
6715 x_clear_area (f
, left
, top
, pixel_width
, height
);
6719 bar
= x_scroll_bar_create (w
, top
, left
, width
, height
, true);
6723 /* It may just need to be moved and resized. */
6724 unsigned int mask
= 0;
6726 bar
= XSCROLL_BAR (w
->horizontal_scroll_bar
);
6730 if (left
!= bar
->left
)
6732 if (top
!= bar
->top
)
6734 if (width
!= bar
->width
)
6736 if (height
!= bar
->height
)
6739 #ifdef USE_TOOLKIT_SCROLL_BARS
6740 /* Move/size the scroll bar widget. */
6743 /* Since toolkit scroll bars are smaller than the space reserved
6744 for them on the frame, we have to clear "under" them. */
6745 if (width
> 0 && height
> 0)
6747 WINDOW_LEFT_EDGE_X (w
), top
,
6748 pixel_width
- WINDOW_RIGHT_DIVIDER_WIDTH (w
), height
);
6750 xg_update_horizontal_scrollbar_pos (f
, bar
->x_window
, top
, left
,
6752 #else /* not USE_GTK */
6753 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
6754 left
, top
, width
, height
, 0);
6755 #endif /* not USE_GTK */
6757 #else /* not USE_TOOLKIT_SCROLL_BARS */
6759 /* Clear areas not covered by the scroll bar because it's not as
6760 wide as the area reserved for it. This makes sure a
6761 previous mode line display is cleared after C-x 2 C-x 1, for
6764 int area_height
= WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w
);
6765 int rest
= area_height
- height
;
6766 if (rest
> 0 && width
> 0)
6767 x_clear_area (f
, left
, top
, width
, rest
);
6770 /* Move/size the scroll bar window. */
6779 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
6783 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6785 /* Remember new settings. */
6789 bar
->height
= height
;
6794 #ifdef USE_TOOLKIT_SCROLL_BARS
6795 x_set_toolkit_horizontal_scroll_bar_thumb (bar
, portion
, position
, whole
);
6796 #else /* not USE_TOOLKIT_SCROLL_BARS */
6797 /* Set the scroll bar's current state, unless we're currently being
6799 if (bar
->dragging
== -1)
6801 int left_range
= HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f
, width
);
6804 x_scroll_bar_set_handle (bar
, 0, left_range
, false);
6807 int start
= ((double) position
* left_range
) / whole
;
6808 int end
= ((double) (position
+ portion
) * left_range
) / whole
;
6809 x_scroll_bar_set_handle (bar
, start
, end
, false);
6812 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6814 XSETVECTOR (barobj
, bar
);
6815 wset_horizontal_scroll_bar (w
, barobj
);
6819 /* The following three hooks are used when we're doing a thorough
6820 redisplay of the frame. We don't explicitly know which scroll bars
6821 are going to be deleted, because keeping track of when windows go
6822 away is a real pain - "Can you say set-window-configuration, boys
6823 and girls?" Instead, we just assert at the beginning of redisplay
6824 that *all* scroll bars are to be removed, and then save a scroll bar
6825 from the fiery pit when we actually redisplay its window. */
6827 /* Arrange for all scroll bars on FRAME to be removed at the next call
6828 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
6829 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
6832 XTcondemn_scroll_bars (struct frame
*frame
)
6834 if (!NILP (FRAME_SCROLL_BARS (frame
)))
6836 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
6838 /* Prepend scrollbars to already condemned ones. */
6839 Lisp_Object last
= FRAME_SCROLL_BARS (frame
);
6841 while (!NILP (XSCROLL_BAR (last
)->next
))
6842 last
= XSCROLL_BAR (last
)->next
;
6844 XSCROLL_BAR (last
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
6845 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= last
;
6848 fset_condemned_scroll_bars (frame
, FRAME_SCROLL_BARS (frame
));
6849 fset_scroll_bars (frame
, Qnil
);
6854 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
6855 Note that WINDOW isn't necessarily condemned at all. */
6858 XTredeem_scroll_bar (struct window
*w
)
6860 struct scroll_bar
*bar
;
6864 /* We can't redeem this window's scroll bar if it doesn't have one. */
6865 if (NILP (w
->vertical_scroll_bar
) && NILP (w
->horizontal_scroll_bar
))
6868 if (!NILP (w
->vertical_scroll_bar
) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
6870 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
6871 /* Unlink it from the condemned list. */
6872 f
= XFRAME (WINDOW_FRAME (w
));
6873 if (NILP (bar
->prev
))
6875 /* If the prev pointer is nil, it must be the first in one of
6877 if (EQ (FRAME_SCROLL_BARS (f
), w
->vertical_scroll_bar
))
6878 /* It's not condemned. Everything's fine. */
6880 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
6881 w
->vertical_scroll_bar
))
6882 fset_condemned_scroll_bars (f
, bar
->next
);
6884 /* If its prev pointer is nil, it must be at the front of
6885 one or the other! */
6889 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
6891 if (! NILP (bar
->next
))
6892 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
6894 bar
->next
= FRAME_SCROLL_BARS (f
);
6896 XSETVECTOR (barobj
, bar
);
6897 fset_scroll_bars (f
, barobj
);
6898 if (! NILP (bar
->next
))
6899 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
6903 if (!NILP (w
->horizontal_scroll_bar
) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w
))
6905 bar
= XSCROLL_BAR (w
->horizontal_scroll_bar
);
6906 /* Unlink it from the condemned list. */
6907 f
= XFRAME (WINDOW_FRAME (w
));
6908 if (NILP (bar
->prev
))
6910 /* If the prev pointer is nil, it must be the first in one of
6912 if (EQ (FRAME_SCROLL_BARS (f
), w
->horizontal_scroll_bar
))
6913 /* It's not condemned. Everything's fine. */
6915 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
6916 w
->horizontal_scroll_bar
))
6917 fset_condemned_scroll_bars (f
, bar
->next
);
6919 /* If its prev pointer is nil, it must be at the front of
6920 one or the other! */
6924 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
6926 if (! NILP (bar
->next
))
6927 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
6929 bar
->next
= FRAME_SCROLL_BARS (f
);
6931 XSETVECTOR (barobj
, bar
);
6932 fset_scroll_bars (f
, barobj
);
6933 if (! NILP (bar
->next
))
6934 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
6938 /* Remove all scroll bars on FRAME that haven't been saved since the
6939 last call to `*condemn_scroll_bars_hook'. */
6942 XTjudge_scroll_bars (struct frame
*f
)
6944 Lisp_Object bar
, next
;
6946 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
6948 /* Clear out the condemned list now so we won't try to process any
6949 more events on the hapless scroll bars. */
6950 fset_condemned_scroll_bars (f
, Qnil
);
6952 for (; ! NILP (bar
); bar
= next
)
6954 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
6956 x_scroll_bar_remove (b
);
6959 b
->next
= b
->prev
= Qnil
;
6962 /* Now there should be no references to the condemned scroll bars,
6963 and they should get garbage-collected. */
6967 #ifndef USE_TOOLKIT_SCROLL_BARS
6968 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
6969 is a no-op when using toolkit scroll bars.
6971 This may be called from a signal handler, so we have to ignore GC
6975 x_scroll_bar_expose (struct scroll_bar
*bar
, const XEvent
*event
)
6977 Window w
= bar
->x_window
;
6978 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6979 GC gc
= f
->output_data
.x
->normal_gc
;
6983 x_scroll_bar_set_handle (bar
, bar
->start
, bar
->end
, true);
6985 /* Switch to scroll bar foreground color. */
6986 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
6987 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
6988 f
->output_data
.x
->scroll_bar_foreground_pixel
);
6990 /* Draw a one-pixel border just inside the edges of the scroll bar. */
6991 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
6992 /* x, y, width, height */
6993 0, 0, bar
->width
- 1, bar
->height
- 1);
6995 /* Restore the foreground color of the GC if we changed it above. */
6996 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
6997 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
6998 FRAME_FOREGROUND_PIXEL (f
));
7003 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7005 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
7006 is set to something other than NO_EVENT, it is enqueued.
7008 This may be called from a signal handler, so we have to ignore GC
7013 x_scroll_bar_handle_click (struct scroll_bar
*bar
,
7014 const XEvent
*event
,
7015 struct input_event
*emacs_event
)
7017 if (! WINDOWP (bar
->window
))
7020 emacs_event
->kind
= (bar
->horizontal
7021 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
7022 : SCROLL_BAR_CLICK_EVENT
);
7023 emacs_event
->code
= event
->xbutton
.button
- Button1
;
7024 emacs_event
->modifiers
7025 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
7026 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
7027 event
->xbutton
.state
)
7028 | (event
->type
== ButtonRelease
7031 emacs_event
->frame_or_window
= bar
->window
;
7032 emacs_event
->arg
= Qnil
;
7033 emacs_event
->timestamp
= event
->xbutton
.time
;
7034 if (bar
->horizontal
)
7037 = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f
, bar
->width
);
7038 int x
= event
->xbutton
.x
- HORIZONTAL_SCROLL_BAR_LEFT_BORDER
;
7041 if (x
> left_range
) x
= left_range
;
7044 emacs_event
->part
= scroll_bar_before_handle
;
7045 else if (x
< bar
->end
+ HORIZONTAL_SCROLL_BAR_MIN_HANDLE
)
7046 emacs_event
->part
= scroll_bar_horizontal_handle
;
7048 emacs_event
->part
= scroll_bar_after_handle
;
7050 #ifndef USE_TOOLKIT_SCROLL_BARS
7051 /* If the user has released the handle, set it to its final position. */
7052 if (event
->type
== ButtonRelease
&& bar
->dragging
!= -1)
7054 int new_start
= - bar
->dragging
;
7055 int new_end
= new_start
+ bar
->end
- bar
->start
;
7057 x_scroll_bar_set_handle (bar
, new_start
, new_end
, false);
7062 XSETINT (emacs_event
->x
, left_range
);
7063 XSETINT (emacs_event
->y
, x
);
7068 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
7069 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
7072 if (y
> top_range
) y
= top_range
;
7075 emacs_event
->part
= scroll_bar_above_handle
;
7076 else if (y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
7077 emacs_event
->part
= scroll_bar_handle
;
7079 emacs_event
->part
= scroll_bar_below_handle
;
7081 #ifndef USE_TOOLKIT_SCROLL_BARS
7082 /* If the user has released the handle, set it to its final position. */
7083 if (event
->type
== ButtonRelease
&& bar
->dragging
!= -1)
7085 int new_start
= y
- bar
->dragging
;
7086 int new_end
= new_start
+ bar
->end
- bar
->start
;
7088 x_scroll_bar_set_handle (bar
, new_start
, new_end
, false);
7093 XSETINT (emacs_event
->x
, y
);
7094 XSETINT (emacs_event
->y
, top_range
);
7098 #ifndef USE_TOOLKIT_SCROLL_BARS
7100 /* Handle some mouse motion while someone is dragging the scroll bar.
7102 This may be called from a signal handler, so we have to ignore GC
7106 x_scroll_bar_note_movement (struct scroll_bar
*bar
,
7107 const XMotionEvent
*event
)
7109 struct frame
*f
= XFRAME (XWINDOW (bar
->window
)->frame
);
7110 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
7112 dpyinfo
->last_mouse_movement_time
= event
->time
;
7113 dpyinfo
->last_mouse_scroll_bar
= bar
;
7114 f
->mouse_moved
= true;
7116 /* If we're dragging the bar, display it. */
7117 if (bar
->dragging
!= -1)
7119 /* Where should the handle be now? */
7120 int new_start
= event
->y
- bar
->dragging
;
7122 if (new_start
!= bar
->start
)
7124 int new_end
= new_start
+ bar
->end
- bar
->start
;
7126 x_scroll_bar_set_handle (bar
, new_start
, new_end
, false);
7131 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7133 /* Return information to the user about the current position of the mouse
7134 on the scroll bar. */
7137 x_scroll_bar_report_motion (struct frame
**fp
, Lisp_Object
*bar_window
,
7138 enum scroll_bar_part
*part
, Lisp_Object
*x
,
7139 Lisp_Object
*y
, Time
*timestamp
)
7141 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
7142 struct scroll_bar
*bar
= dpyinfo
->last_mouse_scroll_bar
;
7143 Window w
= bar
->x_window
;
7144 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7146 Window dummy_window
;
7148 unsigned int dummy_mask
;
7152 /* Get the mouse's position relative to the scroll bar window, and
7154 if (XQueryPointer (FRAME_X_DISPLAY (f
), w
,
7156 /* Root, child, root x and root y. */
7157 &dummy_window
, &dummy_window
,
7158 &dummy_coord
, &dummy_coord
,
7160 /* Position relative to scroll bar. */
7163 /* Mouse buttons and modifier keys. */
7166 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
7168 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
7170 if (bar
->dragging
!= -1)
7171 win_y
-= bar
->dragging
;
7175 if (win_y
> top_range
)
7179 *bar_window
= bar
->window
;
7181 if (bar
->dragging
!= -1)
7182 *part
= scroll_bar_handle
;
7183 else if (win_y
< bar
->start
)
7184 *part
= scroll_bar_above_handle
;
7185 else if (win_y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
7186 *part
= scroll_bar_handle
;
7188 *part
= scroll_bar_below_handle
;
7190 XSETINT (*x
, win_y
);
7191 XSETINT (*y
, top_range
);
7193 f
->mouse_moved
= false;
7194 dpyinfo
->last_mouse_scroll_bar
= NULL
;
7195 *timestamp
= dpyinfo
->last_mouse_movement_time
;
7202 /* Return information to the user about the current position of the mouse
7203 on the scroll bar. */
7206 x_horizontal_scroll_bar_report_motion (struct frame
**fp
, Lisp_Object
*bar_window
,
7207 enum scroll_bar_part
*part
, Lisp_Object
*x
,
7208 Lisp_Object
*y
, Time
*timestamp
)
7210 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
7211 struct scroll_bar
*bar
= dpyinfo
->last_mouse_scroll_bar
;
7212 Window w
= bar
->x_window
;
7213 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7215 Window dummy_window
;
7217 unsigned int dummy_mask
;
7221 /* Get the mouse's position relative to the scroll bar window, and
7223 if (XQueryPointer (FRAME_X_DISPLAY (f
), w
,
7225 /* Root, child, root x and root y. */
7226 &dummy_window
, &dummy_window
,
7227 &dummy_coord
, &dummy_coord
,
7229 /* Position relative to scroll bar. */
7232 /* Mouse buttons and modifier keys. */
7235 int left_range
= HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f
, bar
->width
);
7237 win_x
-= HORIZONTAL_SCROLL_BAR_LEFT_BORDER
;
7239 if (bar
->dragging
!= -1)
7240 win_x
-= bar
->dragging
;
7244 if (win_x
> left_range
)
7248 *bar_window
= bar
->window
;
7250 if (bar
->dragging
!= -1)
7251 *part
= scroll_bar_horizontal_handle
;
7252 else if (win_x
< bar
->start
)
7253 *part
= scroll_bar_before_handle
;
7254 else if (win_x
< bar
->end
+ HORIZONTAL_SCROLL_BAR_MIN_HANDLE
)
7255 *part
= scroll_bar_handle
;
7257 *part
= scroll_bar_after_handle
;
7259 XSETINT (*y
, win_x
);
7260 XSETINT (*x
, left_range
);
7262 f
->mouse_moved
= false;
7263 dpyinfo
->last_mouse_scroll_bar
= NULL
;
7264 *timestamp
= dpyinfo
->last_mouse_movement_time
;
7271 /* The screen has been cleared so we may have changed foreground or
7272 background colors, and the scroll bars may need to be redrawn.
7273 Clear out the scroll bars, and ask for expose events, so we can
7277 x_scroll_bar_clear (struct frame
*f
)
7279 #ifndef USE_TOOLKIT_SCROLL_BARS
7282 /* We can have scroll bars even if this is 0,
7283 if we just turned off scroll bar mode.
7284 But in that case we should not clear them. */
7285 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
7286 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
7287 bar
= XSCROLL_BAR (bar
)->next
)
7288 XClearArea (FRAME_X_DISPLAY (f
),
7289 XSCROLL_BAR (bar
)->x_window
,
7291 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7294 #ifdef ENABLE_CHECKING
7296 /* Record the last 100 characters stored
7297 to help debug the loss-of-chars-during-GC problem. */
7299 static int temp_index
;
7300 static short temp_buffer
[100];
7302 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
7303 if (temp_index == ARRAYELTS (temp_buffer)) \
7305 temp_buffer[temp_index++] = (keysym)
7307 #else /* not ENABLE_CHECKING */
7309 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
7311 #endif /* ENABLE_CHECKING */
7313 /* Set this to nonzero to fake an "X I/O error"
7314 on a particular display. */
7316 static struct x_display_info
*XTread_socket_fake_io_error
;
7318 /* When we find no input here, we occasionally do a no-op command
7319 to verify that the X server is still running and we can still talk with it.
7320 We try all the open displays, one by one.
7321 This variable is used for cycling thru the displays. */
7323 static struct x_display_info
*next_noop_dpyinfo
;
7332 /* Filter events for the current X input method.
7333 DPYINFO is the display this event is for.
7334 EVENT is the X event to filter.
7336 Returns non-zero if the event was filtered, caller shall not process
7338 Returns zero if event is wasn't filtered. */
7342 x_filter_event (struct x_display_info
*dpyinfo
, XEvent
*event
)
7344 /* XFilterEvent returns non-zero if the input method has
7345 consumed the event. We pass the frame's X window to
7346 XFilterEvent because that's the one for which the IC
7349 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
7350 event
->xclient
.window
);
7352 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
7357 static int current_count
;
7358 static int current_finish
;
7359 static struct input_event
*current_hold_quit
;
7361 /* This is the filter function invoked by the GTK event loop.
7362 It is invoked before the XEvent is translated to a GdkEvent,
7363 so we have a chance to act on the event before GTK. */
7364 static GdkFilterReturn
7365 event_handler_gdk (GdkXEvent
*gxev
, GdkEvent
*ev
, gpointer data
)
7367 XEvent
*xev
= (XEvent
*) gxev
;
7370 if (current_count
>= 0)
7372 struct x_display_info
*dpyinfo
;
7374 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
7377 /* Filter events for the current X input method.
7378 GTK calls XFilterEvent but not for key press and release,
7379 so we do it here. */
7380 if ((xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
7382 && x_filter_event (dpyinfo
, xev
))
7385 return GDK_FILTER_REMOVE
;
7390 current_finish
= X_EVENT_NORMAL
;
7393 += handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
7397 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
7401 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
7402 return GDK_FILTER_REMOVE
;
7404 return GDK_FILTER_CONTINUE
;
7406 #endif /* USE_GTK */
7409 static void xembed_send_message (struct frame
*f
, Time
,
7410 enum xembed_message
,
7411 long detail
, long data1
, long data2
);
7414 x_net_wm_state (struct frame
*f
, Window window
)
7416 int value
= FULLSCREEN_NONE
;
7417 Lisp_Object lval
= Qnil
;
7418 bool sticky
= false;
7420 get_current_wm_state (f
, window
, &value
, &sticky
);
7424 case FULLSCREEN_WIDTH
:
7427 case FULLSCREEN_HEIGHT
:
7430 case FULLSCREEN_BOTH
:
7433 case FULLSCREEN_MAXIMIZED
:
7438 frame_size_history_add
7439 (f
, Qx_net_wm_state
, 0, 0,
7440 list2 (get_frame_param (f
, Qfullscreen
), lval
));
7442 store_frame_param (f
, Qfullscreen
, lval
);
7443 /** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
7446 /* Handles the XEvent EVENT on display DPYINFO.
7448 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
7449 *FINISH is zero if caller should continue reading events.
7450 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
7451 *EVENT is unchanged unless we're processing KeyPress event.
7453 We return the number of characters stored into the buffer. */
7456 handle_one_xevent (struct x_display_info
*dpyinfo
,
7457 const XEvent
*event
,
7458 int *finish
, struct input_event
*hold_quit
)
7460 union buffered_input_event inev
;
7463 ptrdiff_t nbytes
= 0;
7464 struct frame
*any
, *f
= NULL
;
7465 struct coding_system coding
;
7466 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
7467 /* This holds the state XLookupString needs to implement dead keys
7468 and other tricks known as "compose processing". _X Window System_
7469 says that a portable program can't use this, but Stephen Gildea assures
7470 me that letting the compiler initialize it to zeros will work okay. */
7471 static XComposeStatus compose_status
;
7472 XEvent configureEvent
;
7477 *finish
= X_EVENT_NORMAL
;
7479 EVENT_INIT (inev
.ie
);
7480 inev
.ie
.kind
= NO_EVENT
;
7483 any
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
7485 if (any
&& any
->wait_event_type
== event
->type
)
7486 any
->wait_event_type
= 0; /* Indicates we got it. */
7488 switch (event
->type
)
7492 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_protocols
7493 && event
->xclient
.format
== 32)
7495 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_take_focus
)
7497 /* Use the value returned by x_any_window_to_frame
7498 because this could be the shell widget window
7499 if the frame has no title bar. */
7502 /* Not quite sure this is needed -pd */
7503 if (f
&& FRAME_XIC (f
))
7504 XSetICFocus (FRAME_XIC (f
));
7507 /* Emacs sets WM hints whose `input' field is `true'. This
7508 instructs the WM to set the input focus automatically for
7509 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
7510 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
7511 it has set the focus. So, XSetInputFocus below is not
7514 The call to XSetInputFocus below has also caused trouble. In
7515 cases where the XSetInputFocus done by the WM and the one
7516 below are temporally close (on a fast machine), the call
7517 below can generate additional FocusIn events which confuse
7520 /* Since we set WM_TAKE_FOCUS, we must call
7521 XSetInputFocus explicitly. But not if f is null,
7522 since that might be an event for a deleted frame. */
7525 Display
*d
= event
->xclient
.display
;
7526 /* Catch and ignore errors, in case window has been
7527 iconified by a window manager such as GWM. */
7529 XSetInputFocus (d
, event
->xclient
.window
,
7530 /* The ICCCM says this is
7531 the only valid choice. */
7533 event
->xclient
.data
.l
[1]);
7534 x_uncatch_errors ();
7536 /* Not certain about handling scroll bars here */
7541 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_save_yourself
)
7543 /* Save state modify the WM_COMMAND property to
7544 something which can reinstate us. This notifies
7545 the session manager, who's looking for such a
7546 PropertyNotify. Can restart processing when
7547 a keyboard or mouse event arrives. */
7548 /* If we have a session manager, don't set this.
7549 KDE will then start two Emacsen, one for the
7550 session manager and one for this. */
7552 if (! x_session_have_connection ())
7555 f
= x_top_window_to_frame (dpyinfo
,
7556 event
->xclient
.window
);
7557 /* This is just so we only give real data once
7558 for a single Emacs process. */
7559 if (f
== SELECTED_FRAME ())
7560 XSetCommand (FRAME_X_DISPLAY (f
),
7561 event
->xclient
.window
,
7562 initial_argv
, initial_argc
);
7564 XSetCommand (FRAME_X_DISPLAY (f
),
7565 event
->xclient
.window
,
7571 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_delete_window
)
7575 goto OTHER
; /* May be a dialog that is to be removed */
7577 inev
.ie
.kind
= DELETE_WINDOW_EVENT
;
7578 XSETFRAME (inev
.ie
.frame_or_window
, f
);
7585 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_configure_denied
)
7588 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_window_moved
)
7591 f
= x_window_to_frame (dpyinfo
, event
->xclient
.window
);
7593 new_x
= event
->xclient
.data
.s
[0];
7594 new_y
= event
->xclient
.data
.s
[1];
7598 f
->left_pos
= new_x
;
7605 if (event
->xclient
.message_type
== dpyinfo
->Xatom_editres
)
7609 _XEditResCheckMessages (f
->output_data
.x
->widget
,
7610 NULL
, (XEvent
*) event
, NULL
);
7613 #endif /* HACK_EDITRES */
7615 if (event
->xclient
.message_type
== dpyinfo
->Xatom_DONE
7616 || event
->xclient
.message_type
== dpyinfo
->Xatom_PAGE
)
7618 /* Ghostview job completed. Kill it. We could
7619 reply with "Next" if we received "Page", but we
7620 currently never do because we are interested in
7621 images, only, which should have 1 page. */
7622 Pixmap pixmap
= (Pixmap
) event
->xclient
.data
.l
[1];
7623 f
= x_window_to_frame (dpyinfo
, event
->xclient
.window
);
7626 x_kill_gs_process (pixmap
, f
);
7627 expose_frame (f
, 0, 0, 0, 0);
7631 #ifdef USE_TOOLKIT_SCROLL_BARS
7632 /* Scroll bar callbacks send a ClientMessage from which
7633 we construct an input_event. */
7634 if (event
->xclient
.message_type
== dpyinfo
->Xatom_Scrollbar
)
7636 x_scroll_bar_to_input_event (event
, &inev
.ie
);
7637 *finish
= X_EVENT_GOTO_OUT
;
7640 else if (event
->xclient
.message_type
== dpyinfo
->Xatom_Horizontal_Scrollbar
)
7642 x_horizontal_scroll_bar_to_input_event (event
, &inev
.ie
);
7643 *finish
= X_EVENT_GOTO_OUT
;
7646 #endif /* USE_TOOLKIT_SCROLL_BARS */
7648 /* XEmbed messages from the embedder (if any). */
7649 if (event
->xclient
.message_type
== dpyinfo
->Xatom_XEMBED
)
7651 enum xembed_message msg
= event
->xclient
.data
.l
[1];
7652 if (msg
== XEMBED_FOCUS_IN
|| msg
== XEMBED_FOCUS_OUT
)
7653 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
7655 *finish
= X_EVENT_GOTO_OUT
;
7659 xft_settings_event (dpyinfo
, event
);
7664 if (x_handle_dnd_message (f
, &event
->xclient
, dpyinfo
, &inev
.ie
))
7665 *finish
= X_EVENT_DROP
;
7669 case SelectionNotify
:
7670 x_display_set_last_user_time (dpyinfo
, event
->xselection
.time
);
7671 #ifdef USE_X_TOOLKIT
7672 if (! x_window_to_frame (dpyinfo
, event
->xselection
.requestor
))
7674 #endif /* not USE_X_TOOLKIT */
7675 x_handle_selection_notify (&event
->xselection
);
7678 case SelectionClear
: /* Someone has grabbed ownership. */
7679 x_display_set_last_user_time (dpyinfo
, event
->xselectionclear
.time
);
7680 #ifdef USE_X_TOOLKIT
7681 if (! x_window_to_frame (dpyinfo
, event
->xselectionclear
.window
))
7683 #endif /* USE_X_TOOLKIT */
7685 const XSelectionClearEvent
*eventp
= &event
->xselectionclear
;
7687 inev
.sie
.kind
= SELECTION_CLEAR_EVENT
;
7688 SELECTION_EVENT_DPYINFO (&inev
.sie
) = dpyinfo
;
7689 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
7690 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
7694 case SelectionRequest
: /* Someone wants our selection. */
7695 x_display_set_last_user_time (dpyinfo
, event
->xselectionrequest
.time
);
7696 #ifdef USE_X_TOOLKIT
7697 if (!x_window_to_frame (dpyinfo
, event
->xselectionrequest
.owner
))
7699 #endif /* USE_X_TOOLKIT */
7701 const XSelectionRequestEvent
*eventp
= &event
->xselectionrequest
;
7703 inev
.sie
.kind
= SELECTION_REQUEST_EVENT
;
7704 SELECTION_EVENT_DPYINFO (&inev
.sie
) = dpyinfo
;
7705 SELECTION_EVENT_REQUESTOR (&inev
.sie
) = eventp
->requestor
;
7706 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
7707 SELECTION_EVENT_TARGET (&inev
.sie
) = eventp
->target
;
7708 SELECTION_EVENT_PROPERTY (&inev
.sie
) = eventp
->property
;
7709 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
7713 case PropertyNotify
:
7714 x_display_set_last_user_time (dpyinfo
, event
->xproperty
.time
);
7715 f
= x_top_window_to_frame (dpyinfo
, event
->xproperty
.window
);
7716 if (f
&& event
->xproperty
.atom
== dpyinfo
->Xatom_net_wm_state
)
7718 bool not_hidden
= x_handle_net_wm_state (f
, &event
->xproperty
);
7719 if (not_hidden
&& FRAME_ICONIFIED_P (f
))
7721 /* Gnome shell does not iconify us when C-z is pressed.
7722 It hides the frame. So if our state says we aren't
7723 hidden anymore, treat it as deiconified. */
7724 SET_FRAME_VISIBLE (f
, 1);
7725 SET_FRAME_ICONIFIED (f
, false);
7726 f
->output_data
.x
->has_been_visible
= true;
7727 inev
.ie
.kind
= DEICONIFY_EVENT
;
7728 XSETFRAME (inev
.ie
.frame_or_window
, f
);
7730 else if (! not_hidden
&& ! FRAME_ICONIFIED_P (f
))
7732 SET_FRAME_VISIBLE (f
, 0);
7733 SET_FRAME_ICONIFIED (f
, true);
7734 inev
.ie
.kind
= ICONIFY_EVENT
;
7735 XSETFRAME (inev
.ie
.frame_or_window
, f
);
7739 x_handle_property_notify (&event
->xproperty
);
7740 xft_settings_event (dpyinfo
, event
);
7743 case ReparentNotify
:
7744 f
= x_top_window_to_frame (dpyinfo
, event
->xreparent
.window
);
7747 f
->output_data
.x
->parent_desc
= event
->xreparent
.parent
;
7748 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7750 /* Perhaps reparented due to a WM restart. Reset this. */
7751 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
7752 FRAME_DISPLAY_INFO (f
)->net_supported_window
= 0;
7754 x_set_frame_alpha (f
);
7759 f
= x_window_to_frame (dpyinfo
, event
->xexpose
.window
);
7762 if (!FRAME_VISIBLE_P (f
))
7764 SET_FRAME_VISIBLE (f
, 1);
7765 SET_FRAME_ICONIFIED (f
, false);
7766 f
->output_data
.x
->has_been_visible
= true;
7767 SET_FRAME_GARBAGED (f
);
7772 /* This seems to be needed for GTK 2.6 and later, see
7773 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
7775 event
->xexpose
.x
, event
->xexpose
.y
,
7776 event
->xexpose
.width
, event
->xexpose
.height
);
7778 expose_frame (f
, event
->xexpose
.x
, event
->xexpose
.y
,
7779 event
->xexpose
.width
, event
->xexpose
.height
);
7784 #ifndef USE_TOOLKIT_SCROLL_BARS
7785 struct scroll_bar
*bar
;
7787 #if defined USE_LUCID
7788 /* Submenus of the Lucid menu bar aren't widgets
7789 themselves, so there's no way to dispatch events
7790 to them. Recognize this case separately. */
7792 Widget widget
= x_window_to_menu_bar (event
->xexpose
.window
);
7794 xlwmenu_redisplay (widget
);
7796 #endif /* USE_LUCID */
7798 #ifdef USE_TOOLKIT_SCROLL_BARS
7799 /* Dispatch event to the widget. */
7801 #else /* not USE_TOOLKIT_SCROLL_BARS */
7802 bar
= x_window_to_scroll_bar (event
->xexpose
.display
,
7803 event
->xexpose
.window
, 2);
7806 x_scroll_bar_expose (bar
, event
);
7807 #ifdef USE_X_TOOLKIT
7810 #endif /* USE_X_TOOLKIT */
7811 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7815 case GraphicsExpose
: /* This occurs when an XCopyArea's
7816 source area was obscured or not
7818 f
= x_window_to_frame (dpyinfo
, event
->xgraphicsexpose
.drawable
);
7820 expose_frame (f
, event
->xgraphicsexpose
.x
,
7821 event
->xgraphicsexpose
.y
,
7822 event
->xgraphicsexpose
.width
,
7823 event
->xgraphicsexpose
.height
);
7824 #ifdef USE_X_TOOLKIT
7827 #endif /* USE_X_TOOLKIT */
7830 case NoExpose
: /* This occurs when an XCopyArea's
7831 source area was completely
7836 /* Redo the mouse-highlight after the tooltip has gone. */
7837 if (event
->xunmap
.window
== tip_window
)
7840 x_redo_mouse_highlight (dpyinfo
);
7843 f
= x_top_window_to_frame (dpyinfo
, event
->xunmap
.window
);
7844 if (f
) /* F may no longer exist if
7845 the frame was deleted. */
7847 bool visible
= FRAME_VISIBLE_P (f
);
7848 /* While a frame is unmapped, display generation is
7849 disabled; you don't want to spend time updating a
7850 display that won't ever be seen. */
7851 SET_FRAME_VISIBLE (f
, 0);
7852 /* We can't distinguish, from the event, whether the window
7853 has become iconified or invisible. So assume, if it
7854 was previously visible, than now it is iconified.
7855 But x_make_frame_invisible clears both
7856 the visible flag and the iconified flag;
7857 and that way, we know the window is not iconified now. */
7858 if (visible
|| FRAME_ICONIFIED_P (f
))
7860 SET_FRAME_ICONIFIED (f
, true);
7861 inev
.ie
.kind
= ICONIFY_EVENT
;
7862 XSETFRAME (inev
.ie
.frame_or_window
, f
);
7868 /* We use x_top_window_to_frame because map events can
7869 come for sub-windows and they don't mean that the
7870 frame is visible. */
7871 f
= x_top_window_to_frame (dpyinfo
, event
->xmap
.window
);
7874 bool iconified
= FRAME_ICONIFIED_P (f
);
7876 /* Check if fullscreen was specified before we where mapped the
7877 first time, i.e. from the command line. */
7878 if (!f
->output_data
.x
->has_been_visible
)
7879 x_check_fullscreen (f
);
7881 SET_FRAME_VISIBLE (f
, 1);
7882 SET_FRAME_ICONIFIED (f
, false);
7883 f
->output_data
.x
->has_been_visible
= true;
7887 inev
.ie
.kind
= DEICONIFY_EVENT
;
7888 XSETFRAME (inev
.ie
.frame_or_window
, f
);
7890 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7891 /* Force a redisplay sooner or later to update the
7892 frame titles in case this is the second frame. */
7893 record_asynch_buffer_change ();
7896 xg_frame_resized (f
, -1, -1);
7903 x_display_set_last_user_time (dpyinfo
, event
->xkey
.time
);
7904 ignore_next_mouse_click_timeout
= 0;
7906 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
7907 /* Dispatch KeyPress events when in menu. */
7908 if (popup_activated ())
7914 /* If mouse-highlight is an integer, input clears out
7915 mouse highlighting. */
7916 if (!hlinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
7917 #if ! defined (USE_GTK)
7919 || !EQ (f
->tool_bar_window
, hlinfo
->mouse_face_window
))
7923 clear_mouse_face (hlinfo
);
7924 hlinfo
->mouse_face_hidden
= true;
7927 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
7930 /* Scroll bars consume key events, but we want
7931 the keys to go to the scroll bar's frame. */
7932 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
7933 event
->xkey
.window
);
7934 if (widget
&& XmIsScrollBar (widget
))
7936 widget
= XtParent (widget
);
7937 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
7940 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
7944 KeySym keysym
, orig_keysym
;
7945 /* al%imercury@uunet.uu.net says that making this 81
7946 instead of 80 fixed a bug whereby meta chars made
7949 It seems that some version of XmbLookupString has
7950 a bug of not returning XBufferOverflow in
7951 status_return even if the input is too long to
7952 fit in 81 bytes. So, we must prepare sufficient
7953 bytes for copy_buffer. 513 bytes (256 chars for
7954 two-byte character set) seems to be a fairly good
7955 approximation. -- 2000.8.10 handa@etl.go.jp */
7956 unsigned char copy_buffer
[513];
7957 unsigned char *copy_bufptr
= copy_buffer
;
7958 int copy_bufsiz
= sizeof (copy_buffer
);
7960 Lisp_Object coding_system
= Qlatin_1
;
7962 /* Event will be modified. */
7963 XKeyEvent xkey
= event
->xkey
;
7966 /* Don't pass keys to GTK. A Tab will shift focus to the
7967 tool bar in GTK 2.4. Keys will still go to menus and
7968 dialogs because in that case popup_activated is nonzero
7970 *finish
= X_EVENT_DROP
;
7973 xkey
.state
|= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f
),
7974 extra_keyboard_modifiers
);
7975 modifiers
= xkey
.state
;
7977 /* This will have to go some day... */
7979 /* make_lispy_event turns chars into control chars.
7980 Don't do it here because XLookupString is too eager. */
7981 xkey
.state
&= ~ControlMask
;
7982 xkey
.state
&= ~(dpyinfo
->meta_mod_mask
7983 | dpyinfo
->super_mod_mask
7984 | dpyinfo
->hyper_mod_mask
7985 | dpyinfo
->alt_mod_mask
);
7987 /* In case Meta is ComposeCharacter,
7988 clear its status. According to Markus Ehrnsperger
7989 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
7990 this enables ComposeCharacter to work whether or
7991 not it is combined with Meta. */
7992 if (modifiers
& dpyinfo
->meta_mod_mask
)
7993 memset (&compose_status
, 0, sizeof (compose_status
));
7998 Status status_return
;
8000 coding_system
= Vlocale_coding_system
;
8001 nbytes
= XmbLookupString (FRAME_XIC (f
),
8002 &xkey
, (char *) copy_bufptr
,
8003 copy_bufsiz
, &keysym
,
8005 if (status_return
== XBufferOverflow
)
8007 copy_bufsiz
= nbytes
+ 1;
8008 copy_bufptr
= alloca (copy_bufsiz
);
8009 nbytes
= XmbLookupString (FRAME_XIC (f
),
8010 &xkey
, (char *) copy_bufptr
,
8011 copy_bufsiz
, &keysym
,
8014 /* Xutf8LookupString is a new but already deprecated interface. -stef */
8015 if (status_return
== XLookupNone
)
8017 else if (status_return
== XLookupChars
)
8022 else if (status_return
!= XLookupKeySym
8023 && status_return
!= XLookupBoth
)
8027 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
8028 copy_bufsiz
, &keysym
,
8031 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
8032 copy_bufsiz
, &keysym
,
8036 /* If not using XIM/XIC, and a compose sequence is in progress,
8037 we break here. Otherwise, chars_matched is always 0. */
8038 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
8041 memset (&compose_status
, 0, sizeof (compose_status
));
8042 orig_keysym
= keysym
;
8044 /* Common for all keysym input events. */
8045 XSETFRAME (inev
.ie
.frame_or_window
, f
);
8047 = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f
), modifiers
);
8048 inev
.ie
.timestamp
= xkey
.time
;
8050 /* First deal with keysyms which have defined
8051 translations to characters. */
8052 if (keysym
>= 32 && keysym
< 128)
8053 /* Avoid explicitly decoding each ASCII character. */
8055 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
8056 inev
.ie
.code
= keysym
;
8060 /* Keysyms directly mapped to Unicode characters. */
8061 if (keysym
>= 0x01000000 && keysym
<= 0x0110FFFF)
8063 if (keysym
< 0x01000080)
8064 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
8066 inev
.ie
.kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
8067 inev
.ie
.code
= keysym
& 0xFFFFFF;
8071 /* Now non-ASCII. */
8072 if (HASH_TABLE_P (Vx_keysym_table
)
8073 && (c
= Fgethash (make_number (keysym
),
8078 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
8079 ? ASCII_KEYSTROKE_EVENT
8080 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
8081 inev
.ie
.code
= XFASTINT (c
);
8085 /* Random non-modifier sorts of keysyms. */
8086 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
8087 || keysym
== XK_Delete
8088 #ifdef XK_ISO_Left_Tab
8089 || (keysym
>= XK_ISO_Left_Tab
8090 && keysym
<= XK_ISO_Enter
)
8092 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
8093 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
8095 /* This recognizes the "extended function
8096 keys". It seems there's no cleaner way.
8097 Test IsModifierKey to avoid handling
8098 mode_switch incorrectly. */
8099 || (XK_Select
<= keysym
&& keysym
< XK_KP_Space
)
8101 #ifdef XK_dead_circumflex
8102 || orig_keysym
== XK_dead_circumflex
8104 #ifdef XK_dead_grave
8105 || orig_keysym
== XK_dead_grave
8107 #ifdef XK_dead_tilde
8108 || orig_keysym
== XK_dead_tilde
8110 #ifdef XK_dead_diaeresis
8111 || orig_keysym
== XK_dead_diaeresis
8113 #ifdef XK_dead_macron
8114 || orig_keysym
== XK_dead_macron
8116 #ifdef XK_dead_degree
8117 || orig_keysym
== XK_dead_degree
8119 #ifdef XK_dead_acute
8120 || orig_keysym
== XK_dead_acute
8122 #ifdef XK_dead_cedilla
8123 || orig_keysym
== XK_dead_cedilla
8125 #ifdef XK_dead_breve
8126 || orig_keysym
== XK_dead_breve
8128 #ifdef XK_dead_ogonek
8129 || orig_keysym
== XK_dead_ogonek
8131 #ifdef XK_dead_caron
8132 || orig_keysym
== XK_dead_caron
8134 #ifdef XK_dead_doubleacute
8135 || orig_keysym
== XK_dead_doubleacute
8137 #ifdef XK_dead_abovedot
8138 || orig_keysym
== XK_dead_abovedot
8140 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
8141 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
8142 /* Any "vendor-specific" key is ok. */
8143 || (orig_keysym
& (1 << 28))
8144 || (keysym
!= NoSymbol
&& nbytes
== 0))
8145 && ! (IsModifierKey (orig_keysym
)
8146 /* The symbols from XK_ISO_Lock
8147 to XK_ISO_Last_Group_Lock
8148 don't have real modifiers but
8149 should be treated similarly to
8150 Mode_switch by Emacs. */
8151 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
8152 || (XK_ISO_Lock
<= orig_keysym
8153 && orig_keysym
<= XK_ISO_Last_Group_Lock
)
8157 STORE_KEYSYM_FOR_DEBUG (keysym
);
8158 /* make_lispy_event will convert this to a symbolic
8160 inev
.ie
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8161 inev
.ie
.code
= keysym
;
8165 { /* Raw bytes, not keysym. */
8169 for (i
= 0, nchars
= 0; i
< nbytes
; i
++)
8171 if (ASCII_CHAR_P (copy_bufptr
[i
]))
8173 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
8176 if (nchars
< nbytes
)
8178 /* Decode the input data. */
8180 /* The input should be decoded with `coding_system'
8181 which depends on which X*LookupString function
8182 we used just above and the locale. */
8183 setup_coding_system (coding_system
, &coding
);
8184 coding
.src_multibyte
= false;
8185 coding
.dst_multibyte
= true;
8186 /* The input is converted to events, thus we can't
8187 handle composition. Anyway, there's no XIM that
8188 gives us composition information. */
8189 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
8191 SAFE_NALLOCA (coding
.destination
, MAX_MULTIBYTE_LENGTH
,
8193 coding
.dst_bytes
= MAX_MULTIBYTE_LENGTH
* nbytes
;
8194 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
8195 decode_coding_c_string (&coding
, copy_bufptr
, nbytes
, Qnil
);
8196 nbytes
= coding
.produced
;
8197 nchars
= coding
.produced_char
;
8198 copy_bufptr
= coding
.destination
;
8201 /* Convert the input data to a sequence of
8202 character events. */
8203 for (i
= 0; i
< nbytes
; i
+= len
)
8206 if (nchars
== nbytes
)
8207 ch
= copy_bufptr
[i
], len
= 1;
8209 ch
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
, len
);
8210 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (ch
)
8211 ? ASCII_KEYSTROKE_EVENT
8212 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
8214 kbd_buffer_store_buffered_event (&inev
, hold_quit
);
8219 inev
.ie
.kind
= NO_EVENT
; /* Already stored above. */
8221 if (keysym
== NoSymbol
)
8224 /* FIXME: check side effects and remove this. */
8225 ((XEvent
*) event
)->xkey
= xkey
;
8229 /* Don't dispatch this event since XtDispatchEvent calls
8230 XFilterEvent, and two calls in a row may freeze the
8238 x_display_set_last_user_time (dpyinfo
, event
->xkey
.time
);
8240 /* Don't dispatch this event since XtDispatchEvent calls
8241 XFilterEvent, and two calls in a row may freeze the
8249 x_display_set_last_user_time (dpyinfo
, event
->xcrossing
.time
);
8250 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
8254 if (f
&& x_mouse_click_focus_ignore_position
)
8255 ignore_next_mouse_click_timeout
= event
->xmotion
.time
+ 200;
8257 /* EnterNotify counts as mouse movement,
8258 so update things that depend on mouse position. */
8259 if (f
&& !f
->output_data
.x
->hourglass_p
)
8260 note_mouse_movement (f
, &event
->xmotion
);
8262 /* We may get an EnterNotify on the buttons in the toolbar. In that
8263 case we moved out of any highlighted area and need to note this. */
8264 if (!f
&& dpyinfo
->last_mouse_glyph_frame
)
8265 note_mouse_movement (dpyinfo
->last_mouse_glyph_frame
, &event
->xmotion
);
8270 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
8274 x_display_set_last_user_time (dpyinfo
, event
->xcrossing
.time
);
8275 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
8277 f
= x_top_window_to_frame (dpyinfo
, event
->xcrossing
.window
);
8280 if (f
== hlinfo
->mouse_face_mouse_frame
)
8282 /* If we move outside the frame, then we're
8283 certainly no longer on any text in the frame. */
8284 clear_mouse_face (hlinfo
);
8285 hlinfo
->mouse_face_mouse_frame
= 0;
8288 /* Generate a nil HELP_EVENT to cancel a help-echo.
8289 Do it only if there's something to cancel.
8290 Otherwise, the startup message is cleared when
8291 the mouse leaves the frame. */
8292 if (any_help_event_p
)
8296 /* See comment in EnterNotify above */
8297 else if (dpyinfo
->last_mouse_glyph_frame
)
8298 note_mouse_movement (dpyinfo
->last_mouse_glyph_frame
, &event
->xmotion
);
8303 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
8308 x_display_set_last_user_time (dpyinfo
, event
->xmotion
.time
);
8309 previous_help_echo_string
= help_echo_string
;
8310 help_echo_string
= Qnil
;
8312 f
= (x_mouse_grabbed (dpyinfo
) ? dpyinfo
->last_mouse_frame
8313 : x_window_to_frame (dpyinfo
, event
->xmotion
.window
));
8315 if (hlinfo
->mouse_face_hidden
)
8317 hlinfo
->mouse_face_hidden
= false;
8318 clear_mouse_face (hlinfo
);
8322 if (f
&& xg_event_is_for_scrollbar (f
, event
))
8328 /* Generate SELECT_WINDOW_EVENTs when needed.
8329 Don't let popup menus influence things (bug#1261). */
8330 if (!NILP (Vmouse_autoselect_window
) && !popup_activated ())
8332 static Lisp_Object last_mouse_window
;
8333 Lisp_Object window
= window_from_coordinates
8334 (f
, event
->xmotion
.x
, event
->xmotion
.y
, 0, false);
8336 /* Window will be selected only when it is not selected now and
8337 last mouse movement event was not in it. Minibuffer window
8338 will be selected only when it is active. */
8339 if (WINDOWP (window
)
8340 && !EQ (window
, last_mouse_window
)
8341 && !EQ (window
, selected_window
)
8342 /* For click-to-focus window managers
8343 create event iff we don't leave the
8345 && (focus_follows_mouse
8346 || (EQ (XWINDOW (window
)->frame
,
8347 XWINDOW (selected_window
)->frame
))))
8349 inev
.ie
.kind
= SELECT_WINDOW_EVENT
;
8350 inev
.ie
.frame_or_window
= window
;
8352 /* Remember the last window where we saw the mouse. */
8353 last_mouse_window
= window
;
8355 if (!note_mouse_movement (f
, &event
->xmotion
))
8356 help_echo_string
= previous_help_echo_string
;
8360 #ifndef USE_TOOLKIT_SCROLL_BARS
8361 struct scroll_bar
*bar
8362 = x_window_to_scroll_bar (event
->xmotion
.display
,
8363 event
->xmotion
.window
, 2);
8366 x_scroll_bar_note_movement (bar
, &event
->xmotion
);
8367 #endif /* USE_TOOLKIT_SCROLL_BARS */
8369 /* If we move outside the frame, then we're
8370 certainly no longer on any text in the frame. */
8371 clear_mouse_face (hlinfo
);
8374 /* If the contents of the global variable help_echo_string
8375 has changed, generate a HELP_EVENT. */
8376 if (!NILP (help_echo_string
)
8377 || !NILP (previous_help_echo_string
))
8382 case ConfigureNotify
:
8383 /* An opaque move can generate a stream of events as the window
8384 is dragged around. If the connection round trip time isn't
8385 really short, they may come faster than we can respond to
8386 them, given the multiple queries we can do to check window
8387 manager state, translate coordinates, etc.
8389 So if this ConfigureNotify is immediately followed by another
8390 for the same window, use the info from the latest update, and
8391 consider the events all handled. */
8392 /* Opaque resize may be trickier; ConfigureNotify events are
8393 mixed with Expose events for multiple windows. */
8394 configureEvent
= *event
;
8395 while (XPending (dpyinfo
->display
))
8397 XNextEvent (dpyinfo
->display
, &next_event
);
8398 if (next_event
.type
!= ConfigureNotify
8399 || next_event
.xconfigure
.window
!= event
->xconfigure
.window
8400 /* Skipping events with different sizes can lead to a
8401 mispositioned mode line at initial window creation.
8402 Only drop window motion events for now. */
8403 || next_event
.xconfigure
.width
!= event
->xconfigure
.width
8404 || next_event
.xconfigure
.height
!= event
->xconfigure
.height
)
8406 XPutBackEvent (dpyinfo
->display
, &next_event
);
8410 configureEvent
= next_event
;
8412 f
= x_top_window_to_frame (dpyinfo
, configureEvent
.xconfigure
.window
);
8414 if (f
) x_cr_destroy_surface (f
);
8419 && configureEvent
.xconfigure
.window
== FRAME_X_WINDOW (f
))
8421 xg_frame_resized (f
, configureEvent
.xconfigure
.width
,
8422 configureEvent
.xconfigure
.height
);
8424 x_cr_destroy_surface (f
);
8431 x_net_wm_state (f
, configureEvent
.xconfigure
.window
);
8433 #ifdef USE_X_TOOLKIT
8434 /* Tip frames are pure X window, set size for them. */
8435 if (! NILP (tip_frame
) && XFRAME (tip_frame
) == f
)
8437 if (FRAME_PIXEL_HEIGHT (f
) != configureEvent
.xconfigure
.height
8438 || FRAME_PIXEL_WIDTH (f
) != configureEvent
.xconfigure
.width
)
8439 SET_FRAME_GARBAGED (f
);
8440 FRAME_PIXEL_HEIGHT (f
) = configureEvent
.xconfigure
.height
;
8441 FRAME_PIXEL_WIDTH (f
) = configureEvent
.xconfigure
.width
;
8445 #ifndef USE_X_TOOLKIT
8448 FRAME_PIXEL_TO_TEXT_WIDTH (f
, configureEvent
.xconfigure
.width
);
8450 FRAME_PIXEL_TO_TEXT_HEIGHT (f
, configureEvent
.xconfigure
.height
);
8452 /* In the toolkit version, change_frame_size
8453 is called by the code that handles resizing
8454 of the EmacsFrame widget. */
8456 /* Even if the number of character rows and columns has
8457 not changed, the font size may have changed, so we need
8458 to check the pixel dimensions as well. */
8459 if (width
!= FRAME_TEXT_WIDTH (f
)
8460 || height
!= FRAME_TEXT_HEIGHT (f
)
8461 || configureEvent
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
8462 || configureEvent
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
8464 change_frame_size (f
, width
, height
, false, true, false, true);
8465 x_clear_under_internal_border (f
);
8466 SET_FRAME_GARBAGED (f
);
8467 cancel_mouse_face (f
);
8469 #endif /* not USE_GTK */
8473 /* GTK creates windows but doesn't map them.
8474 Only get real positions when mapped. */
8475 if (FRAME_GTK_OUTER_WIDGET (f
)
8476 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f
)))
8478 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8481 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
8482 xic_set_statusarea (f
);
8491 /* If we decide we want to generate an event to be seen
8492 by the rest of Emacs, we put it here. */
8493 bool tool_bar_p
= false;
8495 memset (&compose_status
, 0, sizeof (compose_status
));
8496 dpyinfo
->last_mouse_glyph_frame
= NULL
;
8497 x_display_set_last_user_time (dpyinfo
, event
->xbutton
.time
);
8499 f
= (x_mouse_grabbed (dpyinfo
) ? dpyinfo
->last_mouse_frame
8500 : x_window_to_frame (dpyinfo
, event
->xbutton
.window
));
8503 if (f
&& xg_event_is_for_scrollbar (f
, event
))
8508 #if ! defined (USE_GTK)
8509 /* Is this in the tool-bar? */
8510 if (WINDOWP (f
->tool_bar_window
)
8511 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
8514 int x
= event
->xbutton
.x
;
8515 int y
= event
->xbutton
.y
;
8517 window
= window_from_coordinates (f
, x
, y
, 0, true);
8518 tool_bar_p
= EQ (window
, f
->tool_bar_window
);
8520 if (tool_bar_p
&& event
->xbutton
.button
< 4)
8521 handle_tool_bar_click
8522 (f
, x
, y
, event
->xbutton
.type
== ButtonPress
,
8523 x_x_to_emacs_modifiers (dpyinfo
, event
->xbutton
.state
));
8525 #endif /* !USE_GTK */
8528 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8529 if (! popup_activated ())
8532 if (ignore_next_mouse_click_timeout
)
8534 if (event
->type
== ButtonPress
8535 && event
->xbutton
.time
> ignore_next_mouse_click_timeout
)
8537 ignore_next_mouse_click_timeout
= 0;
8538 construct_mouse_click (&inev
.ie
, &event
->xbutton
, f
);
8540 if (event
->type
== ButtonRelease
)
8541 ignore_next_mouse_click_timeout
= 0;
8544 construct_mouse_click (&inev
.ie
, &event
->xbutton
, f
);
8546 if (FRAME_X_EMBEDDED_P (f
))
8547 xembed_send_message (f
, event
->xbutton
.time
,
8548 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
8552 struct scroll_bar
*bar
8553 = x_window_to_scroll_bar (event
->xbutton
.display
,
8554 event
->xbutton
.window
, 2);
8556 #ifdef USE_TOOLKIT_SCROLL_BARS
8557 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
8559 if (bar
&& event
->xbutton
.state
& ControlMask
)
8561 x_scroll_bar_handle_click (bar
, event
, &inev
.ie
);
8562 *finish
= X_EVENT_DROP
;
8564 #else /* not USE_TOOLKIT_SCROLL_BARS */
8566 x_scroll_bar_handle_click (bar
, event
, &inev
.ie
);
8567 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8570 if (event
->type
== ButtonPress
)
8572 dpyinfo
->grabbed
|= (1 << event
->xbutton
.button
);
8573 dpyinfo
->last_mouse_frame
= f
;
8574 #if ! defined (USE_GTK)
8575 if (f
&& !tool_bar_p
)
8576 f
->last_tool_bar_item
= -1;
8577 #endif /* not USE_GTK */
8580 dpyinfo
->grabbed
&= ~(1 << event
->xbutton
.button
);
8582 /* Ignore any mouse motion that happened before this event;
8583 any subsequent mouse-movement Emacs events should reflect
8584 only motion after the ButtonPress/Release. */
8586 f
->mouse_moved
= false;
8588 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
8589 f
= x_menubar_window_to_frame (dpyinfo
, event
);
8590 /* For a down-event in the menu bar,
8591 don't pass it to Xt right now.
8592 Instead, save it away
8593 and we will pass it to Xt from kbd_buffer_get_event.
8594 That way, we can run some Lisp code first. */
8595 if (! popup_activated ()
8597 /* Gtk+ menus only react to the first three buttons. */
8598 && event
->xbutton
.button
< 3
8600 && f
&& event
->type
== ButtonPress
8601 /* Verify the event is really within the menu bar
8602 and not just sent to it due to grabbing. */
8603 && event
->xbutton
.x
>= 0
8604 && event
->xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
8605 && event
->xbutton
.y
>= 0
8606 && event
->xbutton
.y
< FRAME_MENUBAR_HEIGHT (f
)
8607 && event
->xbutton
.same_screen
)
8609 if (!f
->output_data
.x
->saved_menu_event
)
8610 f
->output_data
.x
->saved_menu_event
= xmalloc (sizeof *event
);
8611 *f
->output_data
.x
->saved_menu_event
= *event
;
8612 inev
.ie
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8613 XSETFRAME (inev
.ie
.frame_or_window
, f
);
8614 *finish
= X_EVENT_DROP
;
8618 #endif /* USE_X_TOOLKIT || USE_GTK */
8622 case CirculateNotify
:
8625 case CirculateRequest
:
8628 case VisibilityNotify
:
8632 /* Someone has changed the keyboard mapping - update the
8634 switch (event
->xmapping
.request
)
8636 case MappingModifier
:
8637 x_find_modifier_meanings (dpyinfo
);
8638 /* This is meant to fall through. */
8639 case MappingKeyboard
:
8640 XRefreshKeyboardMapping ((XMappingEvent
*) &event
->xmapping
);
8645 xft_settings_event (dpyinfo
, event
);
8650 #ifdef USE_X_TOOLKIT
8652 if (*finish
!= X_EVENT_DROP
)
8653 XtDispatchEvent ((XEvent
*) event
);
8655 #endif /* USE_X_TOOLKIT */
8660 if (inev
.ie
.kind
!= NO_EVENT
)
8662 kbd_buffer_store_buffered_event (&inev
, hold_quit
);
8667 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
8672 XSETFRAME (frame
, f
);
8678 any_help_event_p
= true;
8679 gen_help_event (help_echo_string
, frame
, help_echo_window
,
8680 help_echo_object
, help_echo_pos
);
8684 help_echo_string
= Qnil
;
8685 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
8694 /* Handles the XEvent EVENT on display DISPLAY.
8695 This is used for event loops outside the normal event handling,
8696 i.e. looping while a popup menu or a dialog is posted.
8698 Returns the value handle_one_xevent sets in the finish argument. */
8700 x_dispatch_event (XEvent
*event
, Display
*display
)
8702 struct x_display_info
*dpyinfo
;
8703 int finish
= X_EVENT_NORMAL
;
8705 dpyinfo
= x_display_info_for_display (display
);
8708 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
8713 /* Read events coming from the X server.
8714 Return as soon as there are no more events to be read.
8716 Return the number of characters stored into the buffer,
8717 thus pretending to be `read' (except the characters we store
8718 in the keyboard buffer can be multibyte, so are not necessarily
8722 XTread_socket (struct terminal
*terminal
, struct input_event
*hold_quit
)
8725 bool event_found
= false;
8726 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
8730 /* For debugging, this gives a way to fake an I/O error. */
8731 if (dpyinfo
== XTread_socket_fake_io_error
)
8733 XTread_socket_fake_io_error
= 0;
8734 x_io_error_quitter (dpyinfo
->display
);
8738 while (XPending (dpyinfo
->display
))
8743 XNextEvent (dpyinfo
->display
, &event
);
8746 /* Filter events for the current X input method. */
8747 if (x_filter_event (dpyinfo
, &event
))
8752 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
8754 if (finish
== X_EVENT_GOTO_OUT
)
8760 /* For GTK we must use the GTK event loop. But XEvents gets passed
8761 to our filter function above, and then to the big event switch.
8762 We use a bunch of globals to communicate with our filter function,
8763 that is kind of ugly, but it works.
8765 There is no way to do one display at the time, GTK just does events
8766 from all displays. */
8768 while (gtk_events_pending ())
8770 current_count
= count
;
8771 current_hold_quit
= hold_quit
;
8773 gtk_main_iteration ();
8775 count
= current_count
;
8777 current_hold_quit
= 0;
8779 if (current_finish
== X_EVENT_GOTO_OUT
)
8782 #endif /* USE_GTK */
8784 /* On some systems, an X bug causes Emacs to get no more events
8785 when the window is destroyed. Detect that. (1994.) */
8788 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
8789 One XNOOP in 100 loops will make Emacs terminate.
8790 B. Bretthauer, 1994 */
8792 if (x_noop_count
>= 100)
8796 if (next_noop_dpyinfo
== 0)
8797 next_noop_dpyinfo
= x_display_list
;
8799 XNoOp (next_noop_dpyinfo
->display
);
8801 /* Each time we get here, cycle through the displays now open. */
8802 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
8806 /* If the focus was just given to an auto-raising frame,
8807 raise it now. FIXME: handle more than one such frame. */
8808 if (dpyinfo
->x_pending_autoraise_frame
)
8810 x_raise_frame (dpyinfo
->x_pending_autoraise_frame
);
8811 dpyinfo
->x_pending_autoraise_frame
= NULL
;
8822 /***********************************************************************
8824 ***********************************************************************/
8826 /* Set clipping for output in glyph row ROW. W is the window in which
8827 we operate. GC is the graphics context to set clipping in.
8829 ROW may be a text row or, e.g., a mode line. Text rows must be
8830 clipped to the interior of the window dedicated to text display,
8831 mode lines must be clipped to the whole window. */
8834 x_clip_to_row (struct window
*w
, struct glyph_row
*row
,
8835 enum glyph_row_area area
, GC gc
)
8837 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8838 XRectangle clip_rect
;
8839 int window_x
, window_y
, window_width
;
8841 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
8843 clip_rect
.x
= window_x
;
8844 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, row
->y
));
8845 clip_rect
.y
= max (clip_rect
.y
, window_y
);
8846 clip_rect
.width
= window_width
;
8847 clip_rect
.height
= row
->visible_height
;
8849 x_set_clip_rectangles (f
, gc
, &clip_rect
, 1);
8853 /* Draw a hollow box cursor on window W in glyph row ROW. */
8856 x_draw_hollow_cursor (struct window
*w
, struct glyph_row
*row
)
8858 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
8859 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8860 Display
*dpy
= FRAME_X_DISPLAY (f
);
8863 struct glyph
*cursor_glyph
;
8866 /* Get the glyph the cursor is on. If we can't tell because
8867 the current matrix is invalid or such, give up. */
8868 cursor_glyph
= get_phys_cursor_glyph (w
);
8869 if (cursor_glyph
== NULL
)
8872 /* Compute frame-relative coordinates for phys cursor. */
8873 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
8874 wd
= w
->phys_cursor_width
- 1;
8876 /* The foreground of cursor_gc is typically the same as the normal
8877 background color, which can cause the cursor box to be invisible. */
8878 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
8879 if (dpyinfo
->scratch_cursor_gc
)
8880 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
8882 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
8883 GCForeground
, &xgcv
);
8884 gc
= dpyinfo
->scratch_cursor_gc
;
8886 /* When on R2L character, show cursor at the right edge of the
8887 glyph, unless the cursor box is as wide as the glyph or wider
8888 (the latter happens when x-stretch-cursor is non-nil). */
8889 if ((cursor_glyph
->resolved_level
& 1) != 0
8890 && cursor_glyph
->pixel_width
> wd
)
8892 x
+= cursor_glyph
->pixel_width
- wd
;
8896 /* Set clipping, draw the rectangle, and reset clipping again. */
8897 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
8898 x_draw_rectangle (f
, gc
, x
, y
, wd
, h
- 1);
8899 x_reset_clip_rectangles (f
, gc
);
8903 /* Draw a bar cursor on window W in glyph row ROW.
8905 Implementation note: One would like to draw a bar cursor with an
8906 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8907 Unfortunately, I didn't find a font yet that has this property set.
8911 x_draw_bar_cursor (struct window
*w
, struct glyph_row
*row
, int width
, enum text_cursor_kinds kind
)
8913 struct frame
*f
= XFRAME (w
->frame
);
8914 struct glyph
*cursor_glyph
;
8916 /* If cursor is out of bounds, don't draw garbage. This can happen
8917 in mini-buffer windows when switching between echo area glyphs
8919 cursor_glyph
= get_phys_cursor_glyph (w
);
8920 if (cursor_glyph
== NULL
)
8923 /* If on an image, draw like a normal cursor. That's usually better
8924 visible than drawing a bar, esp. if the image is large so that
8925 the bar might not be in the window. */
8926 if (cursor_glyph
->type
== IMAGE_GLYPH
)
8928 struct glyph_row
*r
;
8929 r
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
8930 draw_phys_cursor_glyph (w
, r
, DRAW_CURSOR
);
8934 Display
*dpy
= FRAME_X_DISPLAY (f
);
8935 Window window
= FRAME_X_WINDOW (f
);
8936 GC gc
= FRAME_DISPLAY_INFO (f
)->scratch_cursor_gc
;
8937 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
8938 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
8941 /* If the glyph's background equals the color we normally draw
8942 the bars cursor in, the bar cursor in its normal color is
8943 invisible. Use the glyph's foreground color instead in this
8944 case, on the assumption that the glyph's colors are chosen so
8945 that the glyph is legible. */
8946 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
8947 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
8949 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
8950 xgcv
.graphics_exposures
= False
;
8953 XChangeGC (dpy
, gc
, mask
, &xgcv
);
8956 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
8957 FRAME_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
8960 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
8962 if (kind
== BAR_CURSOR
)
8964 int x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
8967 width
= FRAME_CURSOR_WIDTH (f
);
8968 width
= min (cursor_glyph
->pixel_width
, width
);
8970 w
->phys_cursor_width
= width
;
8972 /* If the character under cursor is R2L, draw the bar cursor
8973 on the right of its glyph, rather than on the left. */
8974 if ((cursor_glyph
->resolved_level
& 1) != 0)
8975 x
+= cursor_glyph
->pixel_width
- width
;
8977 x_fill_rectangle (f
, gc
, x
,
8978 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
8979 width
, row
->height
);
8981 else /* HBAR_CURSOR */
8983 int dummy_x
, dummy_y
, dummy_h
;
8984 int x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
8987 width
= row
->height
;
8989 width
= min (row
->height
, width
);
8991 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &dummy_x
,
8992 &dummy_y
, &dummy_h
);
8994 if ((cursor_glyph
->resolved_level
& 1) != 0
8995 && cursor_glyph
->pixel_width
> w
->phys_cursor_width
- 1)
8996 x
+= cursor_glyph
->pixel_width
- w
->phys_cursor_width
+ 1;
8997 x_fill_rectangle (f
, gc
, x
,
8998 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
8999 row
->height
- width
),
9000 w
->phys_cursor_width
- 1, width
);
9003 x_reset_clip_rectangles (f
, gc
);
9008 /* RIF: Define cursor CURSOR on frame F. */
9011 x_define_frame_cursor (struct frame
*f
, Cursor cursor
)
9013 if (!f
->pointer_invisible
9014 && f
->output_data
.x
->current_cursor
!= cursor
)
9015 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
9016 f
->output_data
.x
->current_cursor
= cursor
;
9020 /* RIF: Clear area on frame F. */
9023 x_clear_frame_area (struct frame
*f
, int x
, int y
, int width
, int height
)
9025 x_clear_area (f
, x
, y
, width
, height
);
9027 /* Must queue a redraw, because scroll bars might have been cleared. */
9028 if (FRAME_GTK_WIDGET (f
))
9029 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
9034 /* RIF: Draw cursor on window W. */
9037 x_draw_window_cursor (struct window
*w
, struct glyph_row
*glyph_row
, int x
,
9038 int y
, enum text_cursor_kinds cursor_type
,
9039 int cursor_width
, bool on_p
, bool active_p
)
9041 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9045 w
->phys_cursor_type
= cursor_type
;
9046 w
->phys_cursor_on_p
= true;
9048 if (glyph_row
->exact_window_width_line_p
9049 && (glyph_row
->reversed_p
9050 ? (w
->phys_cursor
.hpos
< 0)
9051 : (w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])))
9053 glyph_row
->cursor_in_fringe_p
= true;
9054 draw_fringe_bitmap (w
, glyph_row
, glyph_row
->reversed_p
);
9058 switch (cursor_type
)
9060 case HOLLOW_BOX_CURSOR
:
9061 x_draw_hollow_cursor (w
, glyph_row
);
9064 case FILLED_BOX_CURSOR
:
9065 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
9069 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
9073 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
9077 w
->phys_cursor_width
= 0;
9086 if (w
== XWINDOW (f
->selected_window
))
9087 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
9088 xic_set_preeditarea (w
, x
, y
);
9092 XFlush (FRAME_X_DISPLAY (f
));
9098 /* Make the x-window of frame F use the gnu icon bitmap. */
9101 x_bitmap_icon (struct frame
*f
, Lisp_Object file
)
9103 ptrdiff_t bitmap_id
;
9105 if (FRAME_X_WINDOW (f
) == 0)
9108 /* Free up our existing icon bitmap and mask if any. */
9109 if (f
->output_data
.x
->icon_bitmap
> 0)
9110 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
9111 f
->output_data
.x
->icon_bitmap
= 0;
9116 /* Use gtk_window_set_icon_from_file () if available,
9117 It's not restricted to bitmaps */
9118 if (xg_set_icon (f
, file
))
9120 #endif /* USE_GTK */
9121 bitmap_id
= x_create_bitmap_from_file (f
, file
);
9122 x_create_bitmap_mask (f
, bitmap_id
);
9126 /* Create the GNU bitmap and mask if necessary. */
9127 if (FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
9133 if (xg_set_icon (f
, xg_default_icon_file
)
9134 || xg_set_icon_from_xpm_data (f
, gnu_xpm_bits
))
9136 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= -2;
9140 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
9142 rc
= x_create_bitmap_from_xpm_data (f
, gnu_xpm_bits
);
9144 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
9148 /* If all else fails, use the (black and white) xbm image. */
9151 rc
= x_create_bitmap_from_data (f
, (char *) gnu_xbm_bits
,
9152 gnu_xbm_width
, gnu_xbm_height
);
9156 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
9157 x_create_bitmap_mask (f
, FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
);
9161 /* The first time we create the GNU bitmap and mask,
9162 this increments the ref-count one extra time.
9163 As a result, the GNU bitmap and mask are never freed.
9164 That way, we don't have to worry about allocating it again. */
9165 x_reference_bitmap (f
, FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
);
9167 bitmap_id
= FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
;
9170 x_wm_set_icon_pixmap (f
, bitmap_id
);
9171 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
9177 /* Make the x-window of frame F use a rectangle with text.
9178 Use ICON_NAME as the text. */
9181 x_text_icon (struct frame
*f
, const char *icon_name
)
9183 if (FRAME_X_WINDOW (f
) == 0)
9188 text
.value
= (unsigned char *) icon_name
;
9189 text
.encoding
= XA_STRING
;
9191 text
.nitems
= strlen (icon_name
);
9192 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
9195 if (f
->output_data
.x
->icon_bitmap
> 0)
9196 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
9197 f
->output_data
.x
->icon_bitmap
= 0;
9198 x_wm_set_icon_pixmap (f
, 0);
9203 #define X_ERROR_MESSAGE_SIZE 200
9205 /* If non-nil, this should be a string.
9206 It means catch X errors and store the error message in this string.
9208 The reason we use a stack is that x_catch_error/x_uncatch_error can
9209 be called from a signal handler.
9212 struct x_error_message_stack
{
9213 char string
[X_ERROR_MESSAGE_SIZE
];
9215 x_special_error_handler handler
;
9217 struct x_error_message_stack
*prev
;
9219 static struct x_error_message_stack
*x_error_message
;
9221 /* An X error handler which stores the error message in
9222 *x_error_message. This is called from x_error_handler if
9223 x_catch_errors is in effect. */
9226 x_error_catcher (Display
*display
, XErrorEvent
*event
)
9228 XGetErrorText (display
, event
->error_code
,
9229 x_error_message
->string
,
9230 X_ERROR_MESSAGE_SIZE
);
9231 if (x_error_message
->handler
)
9232 x_error_message
->handler (display
, event
, x_error_message
->string
,
9233 x_error_message
->handler_data
);
9236 /* Begin trapping X errors for display DPY. Actually we trap X errors
9237 for all displays, but DPY should be the display you are actually
9240 After calling this function, X protocol errors no longer cause
9241 Emacs to exit; instead, they are recorded in the string
9242 stored in *x_error_message.
9244 Calling x_check_errors signals an Emacs error if an X error has
9245 occurred since the last call to x_catch_errors or x_check_errors.
9247 Calling x_uncatch_errors resumes the normal error handling.
9248 Calling x_uncatch_errors_after_check is similar, but skips an XSync
9249 to the server, and should be used only immediately after
9250 x_had_errors_p or x_check_errors. */
9253 x_catch_errors_with_handler (Display
*dpy
, x_special_error_handler handler
,
9256 struct x_error_message_stack
*data
= xmalloc (sizeof *data
);
9258 /* Make sure any errors from previous requests have been dealt with. */
9262 data
->string
[0] = 0;
9263 data
->handler
= handler
;
9264 data
->handler_data
= handler_data
;
9265 data
->prev
= x_error_message
;
9266 x_error_message
= data
;
9270 x_catch_errors (Display
*dpy
)
9272 x_catch_errors_with_handler (dpy
, NULL
, NULL
);
9275 /* Undo the last x_catch_errors call.
9276 DPY should be the display that was passed to x_catch_errors.
9278 This version should be used only if the immediately preceding
9279 X-protocol-related thing was x_check_errors or x_had_error_p, both
9280 of which issue XSync calls, so we don't need to re-sync here. */
9283 x_uncatch_errors_after_check (void)
9285 struct x_error_message_stack
*tmp
;
9288 tmp
= x_error_message
;
9289 x_error_message
= x_error_message
->prev
;
9294 /* Undo the last x_catch_errors call.
9295 DPY should be the display that was passed to x_catch_errors. */
9298 x_uncatch_errors (void)
9300 struct x_error_message_stack
*tmp
;
9304 /* The display may have been closed before this function is called.
9305 Check if it is still open before calling XSync. */
9306 if (x_display_info_for_display (x_error_message
->dpy
) != 0)
9307 XSync (x_error_message
->dpy
, False
);
9309 tmp
= x_error_message
;
9310 x_error_message
= x_error_message
->prev
;
9315 /* If any X protocol errors have arrived since the last call to
9316 x_catch_errors or x_check_errors, signal an Emacs error using
9317 sprintf (a buffer, FORMAT, the x error message text) as the text. */
9320 x_check_errors (Display
*dpy
, const char *format
)
9322 /* Make sure to catch any errors incurred so far. */
9325 if (x_error_message
->string
[0])
9327 char string
[X_ERROR_MESSAGE_SIZE
];
9328 memcpy (string
, x_error_message
->string
, X_ERROR_MESSAGE_SIZE
);
9329 x_uncatch_errors ();
9330 error (format
, string
);
9334 /* Nonzero if we had any X protocol errors
9335 since we did x_catch_errors on DPY. */
9338 x_had_errors_p (Display
*dpy
)
9340 /* Make sure to catch any errors incurred so far. */
9343 return x_error_message
->string
[0] != 0;
9346 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
9349 x_clear_errors (Display
*dpy
)
9351 x_error_message
->string
[0] = 0;
9355 /* See comment in unwind_to_catch why calling this is a bad
9356 * idea. --lorentey */
9357 /* Close off all unclosed x_catch_errors calls. */
9360 x_fully_uncatch_errors (void)
9362 while (x_error_message
)
9363 x_uncatch_errors ();
9368 static unsigned int x_wire_count
;
9371 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
9376 /************************************************************************
9378 ************************************************************************/
9380 /* Error message passed to x_connection_closed. */
9382 static char *error_msg
;
9384 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
9385 the text of an error message that lead to the connection loss. */
9388 x_connection_closed (Display
*dpy
, const char *error_message
, bool ioerror
)
9390 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
9391 Lisp_Object frame
, tail
;
9392 ptrdiff_t idx
= SPECPDL_INDEX ();
9394 error_msg
= alloca (strlen (error_message
) + 1);
9395 strcpy (error_msg
, error_message
);
9397 /* Inhibit redisplay while frames are being deleted. */
9398 specbind (Qinhibit_redisplay
, Qt
);
9402 /* Protect display from being closed when we delete the last
9404 dpyinfo
->reference_count
++;
9405 dpyinfo
->terminal
->reference_count
++;
9407 if (ioerror
) dpyinfo
->display
= 0;
9409 /* First delete frames whose mini-buffers are on frames
9410 that are on the dead display. */
9411 FOR_EACH_FRAME (tail
, frame
)
9413 Lisp_Object minibuf_frame
;
9415 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
9416 if (FRAME_X_P (XFRAME (frame
))
9417 && FRAME_X_P (XFRAME (minibuf_frame
))
9418 && ! EQ (frame
, minibuf_frame
)
9419 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
9420 delete_frame (frame
, Qnoelisp
);
9423 /* Now delete all remaining frames on the dead display.
9424 We are now sure none of these is used as the mini-buffer
9425 for another frame that we need to delete. */
9426 FOR_EACH_FRAME (tail
, frame
)
9427 if (FRAME_X_P (XFRAME (frame
))
9428 && FRAME_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
9430 /* Set this to t so that delete_frame won't get confused
9431 trying to find a replacement. */
9432 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame
)), Qt
);
9433 delete_frame (frame
, Qnoelisp
);
9436 /* If DPYINFO is null, this means we didn't open the display in the
9437 first place, so don't try to close it. */
9440 /* We can not call XtCloseDisplay here because it calls XSync.
9441 XSync inside the error handler apparently hangs Emacs. On
9442 current Xt versions, this isn't needed either. */
9444 /* A long-standing GTK bug prevents proper disconnect handling
9445 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
9446 the resulting Glib error message loop filled a user's disk.
9447 To avoid this, kill Emacs unconditionally on disconnect. */
9448 shut_down_emacs (0, Qnil
);
9449 fprintf (stderr
, "%s\n\
9450 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
9451 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
9452 For details, see etc/PROBLEMS.\n",
9455 #endif /* USE_GTK */
9457 /* Indicate that this display is dead. */
9458 dpyinfo
->display
= 0;
9460 dpyinfo
->reference_count
--;
9461 dpyinfo
->terminal
->reference_count
--;
9462 if (dpyinfo
->reference_count
!= 0)
9463 /* We have just closed all frames on this display. */
9468 XSETTERMINAL (tmp
, dpyinfo
->terminal
);
9469 Fdelete_terminal (tmp
, Qnoelisp
);
9473 if (terminal_list
== 0)
9475 fprintf (stderr
, "%s\n", error_msg
);
9476 Fkill_emacs (make_number (70));
9480 totally_unblock_input ();
9482 unbind_to (idx
, Qnil
);
9483 clear_waiting_for_input ();
9485 /* Tell GCC not to suggest attribute 'noreturn' for this function. */
9486 IF_LINT (if (! terminal_list
) return; )
9488 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
9489 longjmp), because returning from this function would get us back into
9490 Xlib's code which will directly call `exit'. */
9491 error ("%s", error_msg
);
9494 /* We specifically use it before defining it, so that gcc doesn't inline it,
9495 otherwise gdb doesn't know how to properly put a breakpoint on it. */
9496 static void x_error_quitter (Display
*, XErrorEvent
*);
9498 /* This is the first-level handler for X protocol errors.
9499 It calls x_error_quitter or x_error_catcher. */
9502 x_error_handler (Display
*display
, XErrorEvent
*event
)
9504 #if defined USE_GTK && defined HAVE_GTK3
9505 if ((event
->error_code
== BadMatch
|| event
->error_code
== BadWindow
)
9506 && event
->request_code
== X_SetInputFocus
)
9512 if (x_error_message
)
9513 x_error_catcher (display
, event
);
9515 x_error_quitter (display
, event
);
9519 /* This is the usual handler for X protocol errors.
9520 It kills all frames on the display that we got the error for.
9521 If that was the only one, it prints an error message and kills Emacs. */
9523 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
9525 /* On older GCC versions, just putting x_error_quitter
9526 after x_error_handler prevents inlining into the former. */
9528 static void NO_INLINE
9529 x_error_quitter (Display
*display
, XErrorEvent
*event
)
9531 char buf
[256], buf1
[356];
9533 /* Ignore BadName errors. They can happen because of fonts
9534 or colors that are not defined. */
9536 if (event
->error_code
== BadName
)
9539 /* Note that there is no real way portable across R3/R4 to get the
9540 original error handler. */
9542 XGetErrorText (display
, event
->error_code
, buf
, sizeof (buf
));
9543 sprintf (buf1
, "X protocol error: %s on protocol request %d",
9544 buf
, event
->request_code
);
9545 x_connection_closed (display
, buf1
, false);
9549 /* This is the handler for X IO errors, always.
9550 It kills all frames on the display that we lost touch with.
9551 If that was the only one, it prints an error message and kills Emacs. */
9554 x_io_error_quitter (Display
*display
)
9558 snprintf (buf
, sizeof buf
, "Connection lost to X server '%s'",
9559 DisplayString (display
));
9560 x_connection_closed (display
, buf
, true);
9564 /* Changing the font of the frame. */
9566 /* Give frame F the font FONT-OBJECT as its default font. The return
9567 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
9568 frame. If it is negative, generate a new fontset from
9572 x_new_font (struct frame
*f
, Lisp_Object font_object
, int fontset
)
9574 struct font
*font
= XFONT_OBJECT (font_object
);
9575 int unit
, font_ascent
, font_descent
;
9576 #ifndef USE_X_TOOLKIT
9577 int old_menu_bar_height
= FRAME_MENU_BAR_HEIGHT (f
);
9578 Lisp_Object fullscreen
;
9582 fontset
= fontset_from_font (font_object
);
9583 FRAME_FONTSET (f
) = fontset
;
9584 if (FRAME_FONT (f
) == font
)
9585 /* This font is already set in frame F. There's nothing more to
9589 FRAME_FONT (f
) = font
;
9590 FRAME_BASELINE_OFFSET (f
) = font
->baseline_offset
;
9591 FRAME_COLUMN_WIDTH (f
) = font
->average_width
;
9592 get_font_ascent_descent (font
, &font_ascent
, &font_descent
);
9593 FRAME_LINE_HEIGHT (f
) = font_ascent
+ font_descent
;
9595 #ifndef USE_X_TOOLKIT
9596 FRAME_MENU_BAR_HEIGHT (f
) = FRAME_MENU_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
);
9599 /* Compute character columns occupied by scrollbar.
9601 Don't do things differently for non-toolkit scrollbars
9603 unit
= FRAME_COLUMN_WIDTH (f
);
9604 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
9605 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
9606 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + unit
- 1) / unit
;
9608 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + unit
- 1) / unit
;
9610 if (FRAME_X_WINDOW (f
) != 0)
9612 /* Don't change the size of a tip frame; there's no point in
9613 doing it because it's done in Fx_show_tip, and it leads to
9614 problems because the tip frame has no widget. */
9615 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
9617 adjust_frame_size (f
, FRAME_COLS (f
) * FRAME_COLUMN_WIDTH (f
),
9618 FRAME_LINES (f
) * FRAME_LINE_HEIGHT (f
), 3,
9620 #ifndef USE_X_TOOLKIT
9621 if (FRAME_MENU_BAR_HEIGHT (f
) != old_menu_bar_height
9622 && !f
->after_make_frame
9623 && (EQ (frame_inhibit_implied_resize
, Qt
)
9624 || (CONSP (frame_inhibit_implied_resize
)
9625 && NILP (Fmemq (Qfont
, frame_inhibit_implied_resize
))))
9626 && (NILP (fullscreen
= get_frame_param (f
, Qfullscreen
))
9627 || EQ (fullscreen
, Qfullwidth
)))
9628 /* If the menu bar height changes, try to keep text height
9631 (f
, -1, FRAME_TEXT_HEIGHT (f
) + FRAME_MENU_BAR_HEIGHT (f
)
9632 - old_menu_bar_height
, 1, false, Qfont
);
9633 #endif /* USE_X_TOOLKIT */
9639 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
9642 xic_set_xfontset (f
, SSDATA (fontset_ascii (fontset
)));
9651 /***********************************************************************
9653 ***********************************************************************/
9659 /* XIM destroy callback function, which is called whenever the
9660 connection to input method XIM dies. CLIENT_DATA contains a
9661 pointer to the x_display_info structure corresponding to XIM. */
9664 xim_destroy_callback (XIM xim
, XPointer client_data
, XPointer call_data
)
9666 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
9667 Lisp_Object frame
, tail
;
9671 /* No need to call XDestroyIC.. */
9672 FOR_EACH_FRAME (tail
, frame
)
9674 struct frame
*f
= XFRAME (frame
);
9675 if (FRAME_X_P (f
) && FRAME_DISPLAY_INFO (f
) == dpyinfo
)
9677 FRAME_XIC (f
) = NULL
;
9678 xic_free_xfontset (f
);
9682 /* No need to call XCloseIM. */
9683 dpyinfo
->xim
= NULL
;
9684 XFree (dpyinfo
->xim_styles
);
9688 #endif /* HAVE_X11R6 */
9690 /* Open the connection to the XIM server on display DPYINFO.
9691 RESOURCE_NAME is the resource name Emacs uses. */
9694 xim_open_dpy (struct x_display_info
*dpyinfo
, char *resource_name
)
9702 XCloseIM (dpyinfo
->xim
);
9703 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
9710 XIMCallback destroy
;
9713 /* Get supported styles and XIM values. */
9714 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
9717 destroy
.callback
= xim_destroy_callback
;
9718 destroy
.client_data
= (XPointer
)dpyinfo
;
9719 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
9725 #endif /* HAVE_XIM */
9726 dpyinfo
->xim
= NULL
;
9730 #ifdef HAVE_X11R6_XIM
9732 /* XIM instantiate callback function, which is called whenever an XIM
9733 server is available. DISPLAY is the display of the XIM.
9734 CLIENT_DATA contains a pointer to an xim_inst_t structure created
9735 when the callback was registered. */
9738 xim_instantiate_callback (Display
*display
, XPointer client_data
, XPointer call_data
)
9740 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
9741 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
9743 /* We don't support multiple XIM connections. */
9747 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
9749 /* Create XIC for the existing frames on the same display, as long
9750 as they have no XIC. */
9751 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
9753 Lisp_Object tail
, frame
;
9756 FOR_EACH_FRAME (tail
, frame
)
9758 struct frame
*f
= XFRAME (frame
);
9761 && FRAME_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
9762 if (FRAME_XIC (f
) == NULL
)
9764 create_frame_xic (f
);
9765 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
9766 xic_set_statusarea (f
);
9767 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
9769 struct window
*w
= XWINDOW (f
->selected_window
);
9770 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
9779 #endif /* HAVE_X11R6_XIM */
9782 /* Open a connection to the XIM server on display DPYINFO.
9783 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
9784 connection only at the first time. On X11R6, open the connection
9785 in the XIM instantiate callback function. */
9788 xim_initialize (struct x_display_info
*dpyinfo
, char *resource_name
)
9790 dpyinfo
->xim
= NULL
;
9794 #ifdef HAVE_X11R6_XIM
9795 struct xim_inst_t
*xim_inst
= xmalloc (sizeof *xim_inst
);
9798 dpyinfo
->xim_callback_data
= xim_inst
;
9799 xim_inst
->dpyinfo
= dpyinfo
;
9800 xim_inst
->resource_name
= xstrdup (resource_name
);
9801 ret
= XRegisterIMInstantiateCallback
9802 (dpyinfo
->display
, dpyinfo
->xrdb
, xim_inst
->resource_name
,
9803 emacs_class
, xim_instantiate_callback
,
9804 /* This is XPointer in XFree86 but (XPointer *)
9805 on Tru64, at least, hence the configure test. */
9806 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
9807 eassert (ret
== True
);
9808 #else /* not HAVE_X11R6_XIM */
9809 xim_open_dpy (dpyinfo
, resource_name
);
9810 #endif /* not HAVE_X11R6_XIM */
9812 #endif /* HAVE_XIM */
9816 /* Close the connection to the XIM server on display DPYINFO. */
9819 xim_close_dpy (struct x_display_info
*dpyinfo
)
9824 #ifdef HAVE_X11R6_XIM
9825 struct xim_inst_t
*xim_inst
= dpyinfo
->xim_callback_data
;
9827 if (dpyinfo
->display
)
9829 Bool ret
= XUnregisterIMInstantiateCallback
9830 (dpyinfo
->display
, dpyinfo
->xrdb
, xim_inst
->resource_name
,
9831 emacs_class
, xim_instantiate_callback
,
9832 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
9833 eassert (ret
== True
);
9835 xfree (xim_inst
->resource_name
);
9837 #endif /* HAVE_X11R6_XIM */
9838 if (dpyinfo
->display
)
9839 XCloseIM (dpyinfo
->xim
);
9840 dpyinfo
->xim
= NULL
;
9841 XFree (dpyinfo
->xim_styles
);
9843 #endif /* HAVE_XIM */
9846 #endif /* not HAVE_X11R6_XIM */
9850 /* Calculate the absolute position in frame F
9851 from its current recorded position values and gravity. */
9854 x_calc_absolute_position (struct frame
*f
)
9856 int flags
= f
->size_hint_flags
;
9858 /* We have nothing to do if the current position
9859 is already for the top-left corner. */
9860 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
9863 /* Treat negative positions as relative to the leftmost bottommost
9864 position that fits on the screen. */
9865 if (flags
& XNegative
)
9866 f
->left_pos
= x_display_pixel_width (FRAME_DISPLAY_INFO (f
))
9867 - FRAME_PIXEL_WIDTH (f
) + f
->left_pos
;
9870 int height
= FRAME_PIXEL_HEIGHT (f
);
9872 #if defined USE_X_TOOLKIT && defined USE_MOTIF
9873 /* Something is fishy here. When using Motif, starting Emacs with
9874 `-g -0-0', the frame appears too low by a few pixels.
9876 This seems to be so because initially, while Emacs is starting,
9877 the column widget's height and the frame's pixel height are
9878 different. The column widget's height is the right one. In
9879 later invocations, when Emacs is up, the frame's pixel height
9882 It's not obvious where the initial small difference comes from.
9883 2000-12-01, gerd. */
9885 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
9888 if (flags
& YNegative
)
9889 f
->top_pos
= x_display_pixel_height (FRAME_DISPLAY_INFO (f
))
9890 - height
+ f
->top_pos
;
9893 /* The left_pos and top_pos
9894 are now relative to the top and left screen edges,
9895 so the flags should correspond. */
9896 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
9899 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9900 to really change the position, and 0 when calling from
9901 x_make_frame_visible (in that case, XOFF and YOFF are the current
9902 position values). It is -1 when calling from x_set_frame_parameters,
9903 which means, do adjust for borders but don't change the gravity. */
9906 x_set_offset (struct frame
*f
, register int xoff
, register int yoff
, int change_gravity
)
9908 int modified_top
, modified_left
;
9910 if (change_gravity
> 0)
9914 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
9916 f
->size_hint_flags
|= XNegative
;
9918 f
->size_hint_flags
|= YNegative
;
9919 f
->win_gravity
= NorthWestGravity
;
9921 x_calc_absolute_position (f
);
9924 x_wm_set_size_hint (f
, 0, false);
9926 modified_left
= f
->left_pos
;
9927 modified_top
= f
->top_pos
;
9929 if (change_gravity
!= 0 && FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
9931 /* Some WMs (twm, wmaker at least) has an offset that is smaller
9932 than the WM decorations. So we use the calculated offset instead
9933 of the WM decoration sizes here (x/y_pixels_outer_diff). */
9934 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
9935 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
9938 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9939 modified_left
, modified_top
);
9941 x_sync_with_move (f
, f
->left_pos
, f
->top_pos
,
9942 FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
);
9944 /* change_gravity is non-zero when this function is called from Lisp to
9945 programmatically move a frame. In that case, we call
9946 x_check_expected_move to discover if we have a "Type A" or "Type B"
9947 window manager, and, for a "Type A" window manager, adjust the position
9950 We call x_check_expected_move if a programmatic move occurred, and
9951 either the window manager type (A/B) is unknown or it is Type A but we
9952 need to compute the top/left offset adjustment for this frame. */
9954 if (change_gravity
!= 0
9955 && (FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
9956 || (FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
9957 && (FRAME_X_OUTPUT (f
)->move_offset_left
== 0
9958 && FRAME_X_OUTPUT (f
)->move_offset_top
== 0))))
9959 x_check_expected_move (f
, modified_left
, modified_top
);
9964 /* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
9965 on the root window for frame F contains ATOMNAME.
9966 This is how a WM check shall be done according to the Window Manager
9967 Specification/Extended Window Manager Hints at
9968 http://freedesktop.org/wiki/Specifications/wm-spec. */
9971 x_wm_supports (struct frame
*f
, Atom want_atom
)
9974 unsigned long actual_size
, bytes_remaining
;
9975 int i
, rc
, actual_format
;
9977 Window wmcheck_window
;
9978 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
9979 Window target_window
= dpyinfo
->root_window
;
9980 int max_len
= 65536;
9981 Display
*dpy
= FRAME_X_DISPLAY (f
);
9982 unsigned char *tmp_data
= NULL
;
9983 Atom target_type
= XA_WINDOW
;
9987 x_catch_errors (dpy
);
9988 rc
= XGetWindowProperty (dpy
, target_window
,
9989 dpyinfo
->Xatom_net_supporting_wm_check
,
9990 0, max_len
, False
, target_type
,
9991 &actual_type
, &actual_format
, &actual_size
,
9992 &bytes_remaining
, &tmp_data
);
9994 if (rc
!= Success
|| actual_type
!= XA_WINDOW
|| x_had_errors_p (dpy
))
9996 if (tmp_data
) XFree (tmp_data
);
9997 x_uncatch_errors ();
10002 wmcheck_window
= *(Window
*) tmp_data
;
10005 /* Check if window exists. */
10006 XSelectInput (dpy
, wmcheck_window
, StructureNotifyMask
);
10007 if (x_had_errors_p (dpy
))
10009 x_uncatch_errors_after_check ();
10014 if (dpyinfo
->net_supported_window
!= wmcheck_window
)
10016 /* Window changed, reload atoms */
10017 if (dpyinfo
->net_supported_atoms
!= NULL
)
10018 XFree (dpyinfo
->net_supported_atoms
);
10019 dpyinfo
->net_supported_atoms
= NULL
;
10020 dpyinfo
->nr_net_supported_atoms
= 0;
10021 dpyinfo
->net_supported_window
= 0;
10023 target_type
= XA_ATOM
;
10025 rc
= XGetWindowProperty (dpy
, target_window
,
10026 dpyinfo
->Xatom_net_supported
,
10027 0, max_len
, False
, target_type
,
10028 &actual_type
, &actual_format
, &actual_size
,
10029 &bytes_remaining
, &tmp_data
);
10031 if (rc
!= Success
|| actual_type
!= XA_ATOM
|| x_had_errors_p (dpy
))
10033 if (tmp_data
) XFree (tmp_data
);
10034 x_uncatch_errors ();
10039 dpyinfo
->net_supported_atoms
= (Atom
*)tmp_data
;
10040 dpyinfo
->nr_net_supported_atoms
= actual_size
;
10041 dpyinfo
->net_supported_window
= wmcheck_window
;
10046 for (i
= 0; !ret
&& i
< dpyinfo
->nr_net_supported_atoms
; ++i
)
10047 ret
= dpyinfo
->net_supported_atoms
[i
] == want_atom
;
10049 x_uncatch_errors ();
10056 set_wm_state (Lisp_Object frame
, bool add
, Atom atom
, Atom value
)
10058 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (XFRAME (frame
));
10060 x_send_client_event (frame
, make_number (0), frame
,
10061 dpyinfo
->Xatom_net_wm_state
,
10063 /* 1 = add, 0 = remove */
10065 (make_number (add
),
10067 (make_fixnum_or_float (atom
),
10069 ? list1 (make_fixnum_or_float (value
))
10074 x_set_sticky (struct frame
*f
, Lisp_Object new_value
, Lisp_Object old_value
)
10077 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10079 XSETFRAME (frame
, f
);
10081 set_wm_state (frame
, !NILP (new_value
),
10082 dpyinfo
->Xatom_net_wm_state_sticky
, None
);
10085 /* Return the current _NET_WM_STATE.
10086 SIZE_STATE is set to one of the FULLSCREEN_* values.
10087 Set *STICKY to the sticky state.
10089 Return true iff we are not hidden. */
10092 get_current_wm_state (struct frame
*f
,
10097 unsigned long actual_size
;
10099 bool is_hidden
= false;
10100 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10101 long max_len
= 65536;
10102 Atom target_type
= XA_ATOM
;
10103 /* If XCB is available, we can avoid three XSync calls. */
10105 xcb_get_property_cookie_t prop_cookie
;
10106 xcb_get_property_reply_t
*prop
;
10107 xcb_atom_t
*reply_data
;
10109 Display
*dpy
= FRAME_X_DISPLAY (f
);
10110 unsigned long bytes_remaining
;
10111 int rc
, actual_format
;
10113 unsigned char *tmp_data
= NULL
;
10118 *size_state
= FULLSCREEN_NONE
;
10123 prop_cookie
= xcb_get_property (dpyinfo
->xcb_connection
, 0, window
,
10124 dpyinfo
->Xatom_net_wm_state
,
10125 target_type
, 0, max_len
);
10126 prop
= xcb_get_property_reply (dpyinfo
->xcb_connection
, prop_cookie
, NULL
);
10127 if (prop
&& prop
->type
== target_type
)
10129 int actual_bytes
= xcb_get_property_value_length (prop
);
10130 eassume (0 <= actual_bytes
);
10131 actual_size
= actual_bytes
/ sizeof *reply_data
;
10132 reply_data
= xcb_get_property_value (prop
);
10137 is_hidden
= FRAME_ICONIFIED_P (f
);
10140 x_catch_errors (dpy
);
10141 rc
= XGetWindowProperty (dpy
, window
, dpyinfo
->Xatom_net_wm_state
,
10142 0, max_len
, False
, target_type
,
10143 &actual_type
, &actual_format
, &actual_size
,
10144 &bytes_remaining
, &tmp_data
);
10146 if (rc
== Success
&& actual_type
== target_type
&& ! x_had_errors_p (dpy
))
10147 reply_data
= (Atom
*) tmp_data
;
10151 is_hidden
= FRAME_ICONIFIED_P (f
);
10154 x_uncatch_errors ();
10157 for (i
= 0; i
< actual_size
; ++i
)
10159 Atom a
= reply_data
[i
];
10160 if (a
== dpyinfo
->Xatom_net_wm_state_hidden
)
10162 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_horz
)
10164 if (*size_state
== FULLSCREEN_HEIGHT
)
10165 *size_state
= FULLSCREEN_MAXIMIZED
;
10167 *size_state
= FULLSCREEN_WIDTH
;
10169 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_vert
)
10171 if (*size_state
== FULLSCREEN_WIDTH
)
10172 *size_state
= FULLSCREEN_MAXIMIZED
;
10174 *size_state
= FULLSCREEN_HEIGHT
;
10176 else if (a
== dpyinfo
->Xatom_net_wm_state_fullscreen
)
10177 *size_state
= FULLSCREEN_BOTH
;
10178 else if (a
== dpyinfo
->Xatom_net_wm_state_sticky
)
10185 if (tmp_data
) XFree (tmp_data
);
10189 return ! is_hidden
;
10192 /* Do fullscreen as specified in extended window manager hints */
10195 do_ewmh_fullscreen (struct frame
*f
)
10197 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10198 bool have_net_atom
= x_wm_supports (f
, dpyinfo
->Xatom_net_wm_state
);
10202 get_current_wm_state (f
, FRAME_OUTER_WINDOW (f
), &cur
, &dummy
);
10204 /* Some window managers don't say they support _NET_WM_STATE, but they do say
10205 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
10206 if (!have_net_atom
)
10207 have_net_atom
= x_wm_supports (f
, dpyinfo
->Xatom_net_wm_state_fullscreen
);
10209 if (have_net_atom
&& cur
!= f
->want_fullscreen
)
10213 XSETFRAME (frame
, f
);
10215 /* Keep number of calls to set_wm_state as low as possible.
10216 Some window managers, or possible Gtk+, hangs when too many
10217 are sent at once. */
10218 switch (f
->want_fullscreen
)
10220 case FULLSCREEN_BOTH
:
10221 if (cur
!= FULLSCREEN_BOTH
)
10222 set_wm_state (frame
, true, dpyinfo
->Xatom_net_wm_state_fullscreen
,
10225 case FULLSCREEN_WIDTH
:
10226 if (x_frame_normalize_before_maximize
&& cur
== FULLSCREEN_MAXIMIZED
)
10228 set_wm_state (frame
, false,
10229 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10230 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10231 set_wm_state (frame
, true,
10232 dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
10236 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_HEIGHT
10237 || cur
== FULLSCREEN_MAXIMIZED
)
10238 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
10239 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10240 if (cur
!= FULLSCREEN_MAXIMIZED
|| x_frame_normalize_before_maximize
)
10241 set_wm_state (frame
, true,
10242 dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
10245 case FULLSCREEN_HEIGHT
:
10246 if (x_frame_normalize_before_maximize
&& cur
== FULLSCREEN_MAXIMIZED
)
10248 set_wm_state (frame
, false,
10249 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10250 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10251 set_wm_state (frame
, true,
10252 dpyinfo
->Xatom_net_wm_state_maximized_vert
, None
);
10256 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_WIDTH
10257 || cur
== FULLSCREEN_MAXIMIZED
)
10258 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
10259 dpyinfo
->Xatom_net_wm_state_maximized_horz
);
10260 if (cur
!= FULLSCREEN_MAXIMIZED
|| x_frame_normalize_before_maximize
)
10261 set_wm_state (frame
, true,
10262 dpyinfo
->Xatom_net_wm_state_maximized_vert
, None
);
10265 case FULLSCREEN_MAXIMIZED
:
10266 if (x_frame_normalize_before_maximize
&& cur
== FULLSCREEN_BOTH
)
10268 set_wm_state (frame
, false,
10269 dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
10270 set_wm_state (frame
, true,
10271 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10272 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10274 else if (x_frame_normalize_before_maximize
&& cur
== FULLSCREEN_WIDTH
)
10276 set_wm_state (frame
, false,
10277 dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
10278 set_wm_state (frame
, true,
10279 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10280 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10282 else if (x_frame_normalize_before_maximize
&& cur
== FULLSCREEN_HEIGHT
)
10284 set_wm_state (frame
, false,
10285 dpyinfo
->Xatom_net_wm_state_maximized_vert
, None
);
10286 set_wm_state (frame
, true,
10287 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10288 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10292 if (cur
== FULLSCREEN_BOTH
)
10293 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
10295 else if (cur
== FULLSCREEN_HEIGHT
)
10296 set_wm_state (frame
, true,
10297 dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
10298 else if (cur
== FULLSCREEN_WIDTH
)
10299 set_wm_state (frame
, true, None
,
10300 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10302 set_wm_state (frame
, true,
10303 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10304 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10307 case FULLSCREEN_NONE
:
10308 if (cur
== FULLSCREEN_BOTH
)
10309 set_wm_state (frame
, false, dpyinfo
->Xatom_net_wm_state_fullscreen
,
10312 set_wm_state (frame
, false,
10313 dpyinfo
->Xatom_net_wm_state_maximized_horz
,
10314 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
10317 f
->want_fullscreen
= FULLSCREEN_NONE
;
10321 return have_net_atom
;
10325 XTfullscreen_hook (struct frame
*f
)
10327 if (FRAME_VISIBLE_P (f
))
10330 x_check_fullscreen (f
);
10338 x_handle_net_wm_state (struct frame
*f
, const XPropertyEvent
*event
)
10340 int value
= FULLSCREEN_NONE
;
10342 bool sticky
= false;
10343 bool not_hidden
= get_current_wm_state (f
, event
->window
, &value
, &sticky
);
10348 case FULLSCREEN_WIDTH
:
10351 case FULLSCREEN_HEIGHT
:
10352 lval
= Qfullheight
;
10354 case FULLSCREEN_BOTH
:
10357 case FULLSCREEN_MAXIMIZED
:
10362 frame_size_history_add
10363 (f
, Qx_handle_net_wm_state
, 0, 0,
10364 list2 (get_frame_param (f
, Qfullscreen
), lval
));
10366 store_frame_param (f
, Qfullscreen
, lval
);
10367 store_frame_param (f
, Qsticky
, sticky
? Qt
: Qnil
);
10372 /* Check if we need to resize the frame due to a fullscreen request.
10373 If so needed, resize the frame. */
10375 x_check_fullscreen (struct frame
*f
)
10377 Lisp_Object lval
= Qnil
;
10379 if (do_ewmh_fullscreen (f
))
10382 if (f
->output_data
.x
->parent_desc
!= FRAME_DISPLAY_INFO (f
)->root_window
)
10383 return; /* Only fullscreen without WM or with EWM hints (above). */
10385 /* Setting fullscreen to nil doesn't do anything. We could save the
10386 last non-fullscreen size and restore it, but it seems like a
10387 lot of work for this unusual case (no window manager running). */
10389 if (f
->want_fullscreen
!= FULLSCREEN_NONE
)
10391 int width
= FRAME_PIXEL_WIDTH (f
), height
= FRAME_PIXEL_HEIGHT (f
);
10392 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10394 switch (f
->want_fullscreen
)
10396 /* No difference between these two when there is no WM */
10397 case FULLSCREEN_MAXIMIZED
:
10399 width
= x_display_pixel_width (dpyinfo
);
10400 height
= x_display_pixel_height (dpyinfo
);
10402 case FULLSCREEN_BOTH
:
10404 width
= x_display_pixel_width (dpyinfo
);
10405 height
= x_display_pixel_height (dpyinfo
);
10407 case FULLSCREEN_WIDTH
:
10409 width
= x_display_pixel_width (dpyinfo
);
10410 height
= height
+ FRAME_MENUBAR_HEIGHT (f
);
10412 case FULLSCREEN_HEIGHT
:
10413 lval
= Qfullheight
;
10414 height
= x_display_pixel_height (dpyinfo
);
10420 frame_size_history_add
10421 (f
, Qx_check_fullscreen
, width
, height
, Qnil
);
10423 x_wm_set_size_hint (f
, 0, false);
10425 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10428 if (FRAME_VISIBLE_P (f
))
10429 x_wait_for_event (f
, ConfigureNotify
);
10432 change_frame_size (f
, width
, height
- FRAME_MENUBAR_HEIGHT (f
),
10433 false, true, false, true);
10438 /* `x_net_wm_state' might have reset the fullscreen frame parameter,
10440 store_frame_param (f
, Qfullscreen
, lval
);
10443 /* This function is called by x_set_offset to determine whether the window
10444 manager interfered with the positioning of the frame. Type A window
10445 managers position the surrounding window manager decorations a small
10446 amount above and left of the user-supplied position. Type B window
10447 managers position the surrounding window manager decorations at the
10448 user-specified position. If we detect a Type A window manager, we
10449 compensate by moving the window right and down by the proper amount. */
10452 x_check_expected_move (struct frame
*f
, int expected_left
, int expected_top
)
10454 int current_left
= 0, current_top
= 0;
10456 /* x_real_positions returns the left and top offsets of the outermost
10457 window manager window around the frame. */
10459 x_real_positions (f
, ¤t_left
, ¤t_top
);
10461 if (current_left
!= expected_left
|| current_top
!= expected_top
)
10463 /* It's a "Type A" window manager. */
10468 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
10469 FRAME_X_OUTPUT (f
)->move_offset_left
= expected_left
- current_left
;
10470 FRAME_X_OUTPUT (f
)->move_offset_top
= expected_top
- current_top
;
10472 /* Now fix the mispositioned frame's location. */
10474 adjusted_left
= expected_left
+ FRAME_X_OUTPUT (f
)->move_offset_left
;
10475 adjusted_top
= expected_top
+ FRAME_X_OUTPUT (f
)->move_offset_top
;
10477 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10478 adjusted_left
, adjusted_top
);
10480 x_sync_with_move (f
, expected_left
, expected_top
, false);
10483 /* It's a "Type B" window manager. We don't have to adjust the
10484 frame's position. */
10486 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
10490 /* Wait for XGetGeometry to return up-to-date position information for a
10491 recently-moved frame. Call this immediately after calling XMoveWindow.
10492 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
10493 frame has been moved to, so we use a fuzzy position comparison instead
10494 of an exact comparison. */
10497 x_sync_with_move (struct frame
*f
, int left
, int top
, bool fuzzy
)
10501 while (count
++ < 50)
10503 int current_left
= 0, current_top
= 0;
10505 /* In theory, this call to XSync only needs to happen once, but in
10506 practice, it doesn't seem to work, hence the need for the surrounding
10509 XSync (FRAME_X_DISPLAY (f
), False
);
10510 x_real_positions (f
, ¤t_left
, ¤t_top
);
10514 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
10517 if (eabs (current_left
- left
) <= 10
10518 && eabs (current_top
- top
) <= 40)
10521 else if (current_left
== left
&& current_top
== top
)
10525 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
10526 will then return up-to-date position info. */
10528 wait_reading_process_output (0, 500000000, 0, false, Qnil
, NULL
, 0);
10532 /* Wait for an event on frame F matching EVENTTYPE. */
10534 x_wait_for_event (struct frame
*f
, int eventtype
)
10536 int level
= interrupt_input_blocked
;
10539 struct timespec tmo
, tmo_at
, time_now
;
10540 int fd
= ConnectionNumber (FRAME_X_DISPLAY (f
));
10542 f
->wait_event_type
= eventtype
;
10544 /* Set timeout to 0.1 second. Hopefully not noticeable.
10545 Maybe it should be configurable. */
10546 tmo
= make_timespec (0, 100 * 1000 * 1000);
10547 tmo_at
= timespec_add (current_timespec (), tmo
);
10549 while (f
->wait_event_type
)
10551 pending_signals
= true;
10552 totally_unblock_input ();
10553 /* XTread_socket is called after unblock. */
10555 interrupt_input_blocked
= level
;
10560 time_now
= current_timespec ();
10561 if (timespec_cmp (tmo_at
, time_now
) < 0)
10564 tmo
= timespec_sub (tmo_at
, time_now
);
10565 if (pselect (fd
+ 1, &fds
, NULL
, NULL
, &tmo
, NULL
) == 0)
10566 break; /* Timeout */
10569 f
->wait_event_type
= 0;
10573 /* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
10574 doesn't have a widget. If CHANGE_GRAVITY, change to
10575 top-left-corner window gravity for this size change and subsequent
10576 size changes. Otherwise leave the window gravity unchanged. */
10579 x_set_window_size_1 (struct frame
*f
, bool change_gravity
,
10580 int width
, int height
)
10582 int pixelwidth
= FRAME_TEXT_TO_PIXEL_WIDTH (f
, width
);
10583 int pixelheight
= FRAME_TEXT_TO_PIXEL_HEIGHT (f
, height
);
10584 int old_width
= FRAME_PIXEL_WIDTH (f
);
10585 int old_height
= FRAME_PIXEL_HEIGHT (f
);
10586 Lisp_Object fullscreen
= get_frame_param (f
, Qfullscreen
);
10588 if (change_gravity
) f
->win_gravity
= NorthWestGravity
;
10589 x_wm_set_size_hint (f
, 0, false);
10591 /* When the frame is fullheight and we only want to change the width
10592 or it is fullwidth and we only want to change the height we should
10593 be able to preserve the fullscreen property. However, due to the
10594 fact that we have to send a resize request anyway, the window
10595 manager will abolish it. At least the respective size should
10596 remain unchanged but giving the frame back its normal size will
10598 if (EQ (fullscreen
, Qfullwidth
) && width
== FRAME_TEXT_WIDTH (f
))
10600 frame_size_history_add
10601 (f
, Qx_set_window_size_1
, width
, height
,
10602 list2 (make_number (old_height
),
10603 make_number (pixelheight
+ FRAME_MENUBAR_HEIGHT (f
))));
10605 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10606 old_width
, pixelheight
+ FRAME_MENUBAR_HEIGHT (f
));
10608 else if (EQ (fullscreen
, Qfullheight
) && height
== FRAME_TEXT_HEIGHT (f
))
10610 frame_size_history_add
10611 (f
, Qx_set_window_size_2
, width
, height
,
10612 list2 (make_number (old_width
), make_number (pixelwidth
)));
10614 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10615 pixelwidth
, old_height
);
10620 frame_size_history_add
10621 (f
, Qx_set_window_size_3
, width
, height
,
10622 list3 (make_number (pixelwidth
+ FRAME_TOOLBAR_WIDTH (f
)),
10623 make_number (pixelheight
+ FRAME_TOOLBAR_HEIGHT (f
)
10624 + FRAME_MENUBAR_HEIGHT (f
)),
10625 make_number (FRAME_MENUBAR_HEIGHT (f
))));
10627 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10628 pixelwidth
, pixelheight
+ FRAME_MENUBAR_HEIGHT (f
));
10634 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10635 receive in the ConfigureNotify event; if we get what we asked
10636 for, then the event won't cause the screen to become garbaged, so
10637 we have to make sure to do it here. */
10638 SET_FRAME_GARBAGED (f
);
10640 /* Now, strictly speaking, we can't be sure that this is accurate,
10641 but the window manager will get around to dealing with the size
10642 change request eventually, and we'll hear how it went when the
10643 ConfigureNotify event gets here.
10645 We could just not bother storing any of this information here,
10646 and let the ConfigureNotify event set everything up, but that
10647 might be kind of confusing to the Lisp code, since size changes
10648 wouldn't be reported in the frame parameters until some random
10649 point in the future when the ConfigureNotify event arrives.
10651 Pass true for DELAY since we can't run Lisp code inside of
10654 /* But the ConfigureNotify may in fact never arrive, and then this is
10655 not right if the frame is visible. Instead wait (with timeout)
10656 for the ConfigureNotify. */
10657 if (FRAME_VISIBLE_P (f
))
10659 x_wait_for_event (f
, ConfigureNotify
);
10661 if (!NILP (fullscreen
))
10662 /* Try to restore fullscreen state. */
10664 store_frame_param (f
, Qfullscreen
, fullscreen
);
10665 x_set_fullscreen (f
, fullscreen
, fullscreen
);
10670 change_frame_size (f
, width
, height
, false, true, false, true);
10676 /* Call this to change the size of frame F's x-window.
10677 If CHANGE_GRAVITY, change to top-left-corner window gravity
10678 for this size change and subsequent size changes.
10679 Otherwise we leave the window gravity unchanged. */
10682 x_set_window_size (struct frame
*f
, bool change_gravity
,
10683 int width
, int height
, bool pixelwise
)
10687 /* The following breaks our calculations. If it's really needed,
10688 think of something else. */
10690 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
10692 int text_width
, text_height
;
10694 /* When the frame is maximized/fullscreen or running under for
10695 example Xmonad, x_set_window_size_1 will be a no-op.
10696 In that case, the right thing to do is extend rows/width to
10697 the current frame size. We do that first if x_set_window_size_1
10698 turns out to not be a no-op (there is no way to know).
10699 The size will be adjusted again if the frame gets a
10700 ConfigureNotify event as a result of x_set_window_size. */
10701 int pixelh
= FRAME_PIXEL_HEIGHT (f
);
10702 #ifdef USE_X_TOOLKIT
10703 /* The menu bar is not part of text lines. The tool bar
10705 pixelh
-= FRAME_MENUBAR_HEIGHT (f
);
10707 text_width
= FRAME_PIXEL_TO_TEXT_WIDTH (f
, FRAME_PIXEL_WIDTH (f
));
10708 text_height
= FRAME_PIXEL_TO_TEXT_HEIGHT (f
, pixelh
);
10710 change_frame_size (f
, text_width
, text_height
, false, true, false, true);
10714 /* Pixelize width and height, if necessary. */
10717 width
= width
* FRAME_COLUMN_WIDTH (f
);
10718 height
= height
* FRAME_LINE_HEIGHT (f
);
10722 if (FRAME_GTK_WIDGET (f
))
10723 xg_frame_set_char_size (f
, width
, height
);
10725 x_set_window_size_1 (f
, change_gravity
, width
, height
);
10726 #else /* not USE_GTK */
10727 x_set_window_size_1 (f
, change_gravity
, width
, height
);
10728 x_clear_under_internal_border (f
);
10729 #endif /* not USE_GTK */
10731 /* If cursor was outside the new size, mark it as off. */
10732 mark_window_cursors_off (XWINDOW (f
->root_window
));
10734 /* Clear out any recollection of where the mouse highlighting was,
10735 since it might be in a place that's outside the new frame size.
10736 Actually checking whether it is outside is a pain in the neck,
10737 so don't try--just let the highlighting be done afresh with new size. */
10738 cancel_mouse_face (f
);
10743 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10746 frame_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
)
10750 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
10751 0, 0, 0, 0, pix_x
, pix_y
);
10755 /* Raise frame F. */
10758 x_raise_frame (struct frame
*f
)
10761 if (FRAME_VISIBLE_P (f
))
10762 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
10763 XFlush (FRAME_X_DISPLAY (f
));
10767 /* Lower frame F. */
10770 x_lower_frame (struct frame
*f
)
10772 if (FRAME_VISIBLE_P (f
))
10775 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
10776 XFlush (FRAME_X_DISPLAY (f
));
10781 /* Request focus with XEmbed */
10784 xembed_request_focus (struct frame
*f
)
10786 /* See XEmbed Protocol Specification at
10787 http://freedesktop.org/wiki/Specifications/xembed-spec */
10788 if (FRAME_VISIBLE_P (f
))
10789 xembed_send_message (f
, CurrentTime
,
10790 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
10793 /* Activate frame with Extended Window Manager Hints */
10796 x_ewmh_activate_frame (struct frame
*f
)
10798 /* See Window Manager Specification/Extended Window Manager Hints at
10799 http://freedesktop.org/wiki/Specifications/wm-spec */
10801 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10803 if (FRAME_VISIBLE_P (f
) && x_wm_supports (f
, dpyinfo
->Xatom_net_active_window
))
10806 XSETFRAME (frame
, f
);
10807 x_send_client_event (frame
, make_number (0), frame
,
10808 dpyinfo
->Xatom_net_active_window
,
10810 list2i (1, dpyinfo
->last_user_time
));
10815 XTframe_raise_lower (struct frame
*f
, bool raise_flag
)
10823 /* XEmbed implementation. */
10825 #if defined USE_X_TOOLKIT || ! defined USE_GTK
10827 /* XEmbed implementation. */
10829 #define XEMBED_VERSION 0
10832 xembed_set_info (struct frame
*f
, enum xembed_info flags
)
10834 unsigned long data
[2];
10835 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
10837 data
[0] = XEMBED_VERSION
;
10840 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10841 dpyinfo
->Xatom_XEMBED_INFO
, dpyinfo
->Xatom_XEMBED_INFO
,
10842 32, PropModeReplace
, (unsigned char *) data
, 2);
10844 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
10847 xembed_send_message (struct frame
*f
, Time t
, enum xembed_message msg
,
10848 long int detail
, long int data1
, long int data2
)
10852 event
.xclient
.type
= ClientMessage
;
10853 event
.xclient
.window
= FRAME_X_OUTPUT (f
)->parent_desc
;
10854 event
.xclient
.message_type
= FRAME_DISPLAY_INFO (f
)->Xatom_XEMBED
;
10855 event
.xclient
.format
= 32;
10856 event
.xclient
.data
.l
[0] = t
;
10857 event
.xclient
.data
.l
[1] = msg
;
10858 event
.xclient
.data
.l
[2] = detail
;
10859 event
.xclient
.data
.l
[3] = data1
;
10860 event
.xclient
.data
.l
[4] = data2
;
10862 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_OUTPUT (f
)->parent_desc
,
10863 False
, NoEventMask
, &event
);
10864 XSync (FRAME_X_DISPLAY (f
), False
);
10867 /* Change of visibility. */
10869 /* This tries to wait until the frame is really visible.
10870 However, if the window manager asks the user where to position
10871 the frame, this will return before the user finishes doing that.
10872 The frame will not actually be visible at that time,
10873 but it will become visible later when the window manager
10874 finishes with it. */
10877 x_make_frame_visible (struct frame
*f
)
10879 int original_top
, original_left
;
10884 x_set_bitmap_icon (f
);
10886 if (! FRAME_VISIBLE_P (f
))
10888 /* We test FRAME_GARBAGED_P here to make sure we don't
10889 call x_set_offset a second time
10890 if we get to x_make_frame_visible a second time
10891 before the window gets really visible. */
10892 if (! FRAME_ICONIFIED_P (f
)
10893 && ! FRAME_X_EMBEDDED_P (f
)
10894 && ! f
->output_data
.x
->asked_for_visible
)
10895 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
10897 f
->output_data
.x
->asked_for_visible
= true;
10899 if (! EQ (Vx_no_window_manager
, Qt
))
10900 x_wm_set_window_state (f
, NormalState
);
10901 #ifdef USE_X_TOOLKIT
10902 if (FRAME_X_EMBEDDED_P (f
))
10903 xembed_set_info (f
, XEMBED_MAPPED
);
10906 /* This was XtPopup, but that did nothing for an iconified frame. */
10907 XtMapWidget (f
->output_data
.x
->widget
);
10909 #else /* not USE_X_TOOLKIT */
10911 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
10912 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
10914 if (FRAME_X_EMBEDDED_P (f
))
10915 xembed_set_info (f
, XEMBED_MAPPED
);
10917 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10918 #endif /* not USE_GTK */
10919 #endif /* not USE_X_TOOLKIT */
10922 XFlush (FRAME_X_DISPLAY (f
));
10924 /* Synchronize to ensure Emacs knows the frame is visible
10925 before we do anything else. We do this loop with input not blocked
10926 so that incoming events are handled. */
10929 /* This must be before UNBLOCK_INPUT
10930 since events that arrive in response to the actions above
10931 will set it when they are handled. */
10932 bool previously_visible
= f
->output_data
.x
->has_been_visible
;
10934 original_left
= f
->left_pos
;
10935 original_top
= f
->top_pos
;
10937 /* This must come after we set COUNT. */
10940 /* We unblock here so that arriving X events are processed. */
10942 /* Now move the window back to where it was "supposed to be".
10943 But don't do it if the gravity is negative.
10944 When the gravity is negative, this uses a position
10945 that is 3 pixels too low. Perhaps that's really the border width.
10947 Don't do this if the window has never been visible before,
10948 because the window manager may choose the position
10949 and we don't want to override it. */
10951 if (! FRAME_VISIBLE_P (f
)
10952 && ! FRAME_ICONIFIED_P (f
)
10953 && ! FRAME_X_EMBEDDED_P (f
)
10954 && f
->win_gravity
== NorthWestGravity
10955 && previously_visible
)
10959 unsigned int width
, height
, border
, depth
;
10963 /* On some window managers (such as FVWM) moving an existing
10964 window, even to the same place, causes the window manager
10965 to introduce an offset. This can cause the window to move
10966 to an unexpected location. Check the geometry (a little
10967 slow here) and then verify that the window is in the right
10968 place. If the window is not in the right place, move it
10969 there, and take the potential window manager hit. */
10970 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10971 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
10973 if (original_left
!= x
|| original_top
!= y
)
10974 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10975 original_left
, original_top
);
10980 XSETFRAME (frame
, f
);
10982 /* Process X events until a MapNotify event has been seen. */
10983 while (!FRAME_VISIBLE_P (f
))
10985 /* Force processing of queued events. */
10988 /* If on another desktop, the deiconify/map may be ignored and the
10989 frame never becomes visible. XMonad does this.
10990 Prevent an endless loop. */
10991 if (FRAME_ICONIFIED_P (f
) && ++tries
> 100)
10994 /* This hack is still in use at least for Cygwin. See
10995 http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html.
10997 Machines that do polling rather than SIGIO have been
10998 observed to go into a busy-wait here. So we'll fake an
10999 alarm signal to let the handler know that there's something
11000 to be read. We used to raise a real alarm, but it seems
11001 that the handler isn't always enabled here. This is
11003 if (input_polling_used ())
11005 /* It could be confusing if a real alarm arrives while
11006 processing the fake one. Turn it off and let the
11007 handler reset it. */
11008 int old_poll_suppress_count
= poll_suppress_count
;
11009 poll_suppress_count
= 1;
11010 poll_for_input_1 ();
11011 poll_suppress_count
= old_poll_suppress_count
;
11014 if (XPending (FRAME_X_DISPLAY (f
)))
11017 XNextEvent (FRAME_X_DISPLAY (f
), &xev
);
11018 x_dispatch_event (&xev
, FRAME_X_DISPLAY (f
));
11024 /* Change from mapped state to withdrawn state. */
11026 /* Make the frame visible (mapped and not iconified). */
11029 x_make_frame_invisible (struct frame
*f
)
11033 /* Use the frame's outermost window, not the one we normally draw on. */
11034 window
= FRAME_OUTER_WINDOW (f
);
11036 /* Don't keep the highlight on an invisible frame. */
11037 if (FRAME_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11038 FRAME_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11042 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11043 that the current position of the window is user-specified, rather than
11044 program-specified, so that when the window is mapped again, it will be
11045 placed at the same location, without forcing the user to position it
11046 by hand again (they have already done that once for this window.) */
11047 x_wm_set_size_hint (f
, 0, true);
11050 if (FRAME_GTK_OUTER_WIDGET (f
))
11051 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
11054 if (FRAME_X_EMBEDDED_P (f
))
11055 xembed_set_info (f
, 0);
11060 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11061 DefaultScreen (FRAME_X_DISPLAY (f
))))
11064 error ("Can't notify window manager of window withdrawal");
11068 /* We can't distinguish this from iconification
11069 just by the event that we get from the server.
11070 So we can't win using the usual strategy of letting
11071 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11072 and synchronize with the server to make sure we agree. */
11073 SET_FRAME_VISIBLE (f
, 0);
11074 SET_FRAME_ICONIFIED (f
, false);
11081 /* Change window state from mapped to iconified. */
11084 x_iconify_frame (struct frame
*f
)
11086 #ifdef USE_X_TOOLKIT
11090 /* Don't keep the highlight on an invisible frame. */
11091 if (FRAME_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11092 FRAME_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11094 if (FRAME_ICONIFIED_P (f
))
11099 x_set_bitmap_icon (f
);
11101 #if defined (USE_GTK)
11102 if (FRAME_GTK_OUTER_WIDGET (f
))
11104 if (! FRAME_VISIBLE_P (f
))
11105 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
11107 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
11108 SET_FRAME_VISIBLE (f
, 0);
11109 SET_FRAME_ICONIFIED (f
, true);
11115 #ifdef USE_X_TOOLKIT
11117 if (! FRAME_VISIBLE_P (f
))
11119 if (! EQ (Vx_no_window_manager
, Qt
))
11120 x_wm_set_window_state (f
, IconicState
);
11121 /* This was XtPopup, but that did nothing for an iconified frame. */
11122 XtMapWidget (f
->output_data
.x
->widget
);
11123 /* The server won't give us any event to indicate
11124 that an invisible frame was changed to an icon,
11125 so we have to record it here. */
11126 SET_FRAME_VISIBLE (f
, 0);
11127 SET_FRAME_ICONIFIED (f
, true);
11132 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11133 XtWindow (f
->output_data
.x
->widget
),
11134 DefaultScreen (FRAME_X_DISPLAY (f
)));
11138 error ("Can't notify window manager of iconification");
11140 SET_FRAME_ICONIFIED (f
, true);
11141 SET_FRAME_VISIBLE (f
, 0);
11144 XFlush (FRAME_X_DISPLAY (f
));
11146 #else /* not USE_X_TOOLKIT */
11148 /* Make sure the X server knows where the window should be positioned,
11149 in case the user deiconifies with the window manager. */
11150 if (! FRAME_VISIBLE_P (f
)
11151 && ! FRAME_ICONIFIED_P (f
)
11152 && ! FRAME_X_EMBEDDED_P (f
))
11153 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
11155 /* Since we don't know which revision of X we're running, we'll use both
11156 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11158 /* X11R4: send a ClientMessage to the window manager using the
11159 WM_CHANGE_STATE type. */
11163 msg
.xclient
.window
= FRAME_X_WINDOW (f
);
11164 msg
.xclient
.type
= ClientMessage
;
11165 msg
.xclient
.message_type
= FRAME_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11166 msg
.xclient
.format
= 32;
11167 msg
.xclient
.data
.l
[0] = IconicState
;
11169 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11170 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11172 SubstructureRedirectMask
| SubstructureNotifyMask
,
11176 error ("Can't notify window manager of iconification");
11180 /* X11R3: set the initial_state field of the window manager hints to
11182 x_wm_set_window_state (f
, IconicState
);
11184 if (!FRAME_VISIBLE_P (f
))
11186 /* If the frame was withdrawn, before, we must map it. */
11187 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11190 SET_FRAME_ICONIFIED (f
, true);
11191 SET_FRAME_VISIBLE (f
, 0);
11193 XFlush (FRAME_X_DISPLAY (f
));
11195 #endif /* not USE_X_TOOLKIT */
11199 /* Free X resources of frame F. */
11202 x_free_frame_resources (struct frame
*f
)
11204 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
11205 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
11206 #ifdef USE_X_TOOLKIT
11208 struct scroll_bar
*b
;
11213 /* If a display connection is dead, don't try sending more
11214 commands to the X server. */
11215 if (dpyinfo
->display
)
11217 /* Always exit with visible pointer to avoid weird issue
11218 with Xfixes (Bug#17609). */
11219 if (f
->pointer_invisible
)
11220 FRAME_DISPLAY_INFO (f
)->toggle_visible_pointer (f
, 0);
11222 /* We must free faces before destroying windows because some
11223 font-driver (e.g. xft) access a window while finishing a
11225 free_frame_faces (f
);
11227 if (f
->output_data
.x
->icon_desc
)
11228 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11230 #ifdef USE_X_TOOLKIT
11231 /* Explicitly destroy the scroll bars of the frame. Without
11232 this, we get "BadDrawable" errors from the toolkit later on,
11233 presumably from expose events generated for the disappearing
11234 toolkit scroll bars. */
11235 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
11237 b
= XSCROLL_BAR (bar
);
11238 x_scroll_bar_remove (b
);
11244 free_frame_xic (f
);
11247 x_free_cr_resources (f
);
11248 #ifdef USE_X_TOOLKIT
11249 if (f
->output_data
.x
->widget
)
11251 XtDestroyWidget (f
->output_data
.x
->widget
);
11252 f
->output_data
.x
->widget
= NULL
;
11254 /* Tooltips don't have widgets, only a simple X window, even if
11255 we are using a toolkit. */
11256 else if (FRAME_X_WINDOW (f
))
11257 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11259 free_frame_menubar (f
);
11261 if (f
->shell_position
)
11262 xfree (f
->shell_position
);
11263 #else /* !USE_X_TOOLKIT */
11266 xg_free_frame_widgets (f
);
11267 #endif /* USE_GTK */
11269 if (FRAME_X_WINDOW (f
))
11270 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11271 #endif /* !USE_X_TOOLKIT */
11273 unload_color (f
, FRAME_FOREGROUND_PIXEL (f
));
11274 unload_color (f
, FRAME_BACKGROUND_PIXEL (f
));
11275 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
11276 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
11277 unload_color (f
, f
->output_data
.x
->border_pixel
);
11278 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
11280 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
11281 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
11282 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
11283 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
11284 #if defined (USE_LUCID) && defined (USE_TOOLKIT_SCROLL_BARS)
11285 /* Scrollbar shadow colors. */
11286 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
11287 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
11288 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
11289 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
11290 #endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
11291 if (f
->output_data
.x
->white_relief
.pixel
!= -1)
11292 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
11293 if (f
->output_data
.x
->black_relief
.pixel
!= -1)
11294 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
11298 /* Free extra GCs allocated by x_setup_relief_colors. */
11299 if (f
->output_data
.x
->white_relief
.gc
)
11301 XFreeGC (dpyinfo
->display
, f
->output_data
.x
->white_relief
.gc
);
11302 f
->output_data
.x
->white_relief
.gc
= 0;
11304 if (f
->output_data
.x
->black_relief
.gc
)
11306 XFreeGC (dpyinfo
->display
, f
->output_data
.x
->black_relief
.gc
);
11307 f
->output_data
.x
->black_relief
.gc
= 0;
11310 /* Free cursors. */
11311 if (f
->output_data
.x
->text_cursor
!= 0)
11312 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
11313 if (f
->output_data
.x
->nontext_cursor
!= 0)
11314 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
11315 if (f
->output_data
.x
->modeline_cursor
!= 0)
11316 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
11317 if (f
->output_data
.x
->hand_cursor
!= 0)
11318 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->hand_cursor
);
11319 if (f
->output_data
.x
->hourglass_cursor
!= 0)
11320 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->hourglass_cursor
);
11321 if (f
->output_data
.x
->horizontal_drag_cursor
!= 0)
11322 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->horizontal_drag_cursor
);
11323 if (f
->output_data
.x
->vertical_drag_cursor
!= 0)
11324 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->vertical_drag_cursor
);
11326 XFlush (FRAME_X_DISPLAY (f
));
11329 xfree (f
->output_data
.x
->saved_menu_event
);
11330 xfree (f
->output_data
.x
);
11331 f
->output_data
.x
= NULL
;
11333 if (f
== dpyinfo
->x_focus_frame
)
11334 dpyinfo
->x_focus_frame
= 0;
11335 if (f
== dpyinfo
->x_focus_event_frame
)
11336 dpyinfo
->x_focus_event_frame
= 0;
11337 if (f
== dpyinfo
->x_highlight_frame
)
11338 dpyinfo
->x_highlight_frame
= 0;
11339 if (f
== hlinfo
->mouse_face_mouse_frame
)
11340 reset_mouse_highlight (hlinfo
);
11346 /* Destroy the X window of frame F. */
11349 x_destroy_window (struct frame
*f
)
11351 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
11353 /* If a display connection is dead, don't try sending more
11354 commands to the X server. */
11355 if (dpyinfo
->display
!= 0)
11356 x_free_frame_resources (f
);
11358 dpyinfo
->reference_count
--;
11362 /* Setting window manager hints. */
11364 /* Set the normal size hints for the window manager, for frame F.
11365 FLAGS is the flags word to use--or 0 meaning preserve the flags
11366 that the window now has.
11367 If USER_POSITION, set the USPosition
11368 flag (this is useful when FLAGS is 0).
11369 The GTK version is in gtkutils.c. */
11373 x_wm_set_size_hint (struct frame
*f
, long flags
, bool user_position
)
11375 XSizeHints size_hints
;
11376 Window window
= FRAME_OUTER_WINDOW (f
);
11381 #ifdef USE_X_TOOLKIT
11382 if (f
->output_data
.x
->widget
)
11384 widget_update_wm_size_hints (f
->output_data
.x
->widget
);
11389 /* Setting PMaxSize caused various problems. */
11390 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11392 size_hints
.x
= f
->left_pos
;
11393 size_hints
.y
= f
->top_pos
;
11395 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
11396 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
11398 size_hints
.width_inc
= frame_resize_pixelwise
? 1 : FRAME_COLUMN_WIDTH (f
);
11399 size_hints
.height_inc
= frame_resize_pixelwise
? 1 : FRAME_LINE_HEIGHT (f
);
11401 size_hints
.max_width
= x_display_pixel_width (FRAME_DISPLAY_INFO (f
))
11402 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
11403 size_hints
.max_height
= x_display_pixel_height (FRAME_DISPLAY_INFO (f
))
11404 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
11406 /* Calculate the base and minimum sizes. */
11408 int base_width
, base_height
;
11410 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
11411 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
11413 /* The window manager uses the base width hints to calculate the
11414 current number of rows and columns in the frame while
11415 resizing; min_width and min_height aren't useful for this
11416 purpose, since they might not give the dimensions for a
11417 zero-row, zero-column frame. */
11419 size_hints
.flags
|= PBaseSize
;
11420 size_hints
.base_width
= base_width
;
11421 size_hints
.base_height
= base_height
+ FRAME_MENUBAR_HEIGHT (f
);
11422 size_hints
.min_width
= base_width
;
11423 size_hints
.min_height
= base_height
;
11426 /* If we don't need the old flags, we don't need the old hint at all. */
11429 size_hints
.flags
|= flags
;
11434 XSizeHints hints
; /* Sometimes I hate X Windows... */
11435 long supplied_return
;
11438 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11442 size_hints
.flags
|= flags
;
11447 if (hints
.flags
& PSize
)
11448 size_hints
.flags
|= PSize
;
11449 if (hints
.flags
& PPosition
)
11450 size_hints
.flags
|= PPosition
;
11451 if (hints
.flags
& USPosition
)
11452 size_hints
.flags
|= USPosition
;
11453 if (hints
.flags
& USSize
)
11454 size_hints
.flags
|= USSize
;
11461 size_hints
.win_gravity
= f
->win_gravity
;
11462 size_hints
.flags
|= PWinGravity
;
11466 size_hints
.flags
&= ~ PPosition
;
11467 size_hints
.flags
|= USPosition
;
11469 #endif /* PWinGravity */
11471 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11473 #endif /* not USE_GTK */
11475 /* Used for IconicState or NormalState */
11478 x_wm_set_window_state (struct frame
*f
, int state
)
11480 #ifdef USE_X_TOOLKIT
11483 XtSetArg (al
[0], XtNinitialState
, state
);
11484 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11485 #else /* not USE_X_TOOLKIT */
11486 Window window
= FRAME_X_WINDOW (f
);
11488 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
11489 f
->output_data
.x
->wm_hints
.initial_state
= state
;
11491 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11492 #endif /* not USE_X_TOOLKIT */
11496 x_wm_set_icon_pixmap (struct frame
*f
, ptrdiff_t pixmap_id
)
11498 Pixmap icon_pixmap
, icon_mask
;
11500 #if !defined USE_X_TOOLKIT && !defined USE_GTK
11501 Window window
= FRAME_OUTER_WINDOW (f
);
11506 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
11507 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
11508 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
11509 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
11513 /* It seems there is no way to turn off use of an icon
11521 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
);
11525 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
11529 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
11530 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11531 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
11532 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11535 #else /* not USE_X_TOOLKIT && not USE_GTK */
11537 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
11538 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11540 #endif /* not USE_X_TOOLKIT && not USE_GTK */
11544 x_wm_set_icon_position (struct frame
*f
, int icon_x
, int icon_y
)
11546 Window window
= FRAME_OUTER_WINDOW (f
);
11548 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
11549 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
11550 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
11552 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11556 /***********************************************************************
11558 ***********************************************************************/
11562 /* Check that FONT is valid on frame F. It is if it can be found in F's
11566 x_check_font (struct frame
*f
, struct font
*font
)
11568 eassert (font
!= NULL
&& ! NILP (font
->props
[FONT_TYPE_INDEX
]));
11569 if (font
->driver
->check
)
11570 eassert (font
->driver
->check (f
, font
) == 0);
11573 #endif /* GLYPH_DEBUG */
11576 /***********************************************************************
11578 ***********************************************************************/
11580 #ifdef USE_X_TOOLKIT
11581 static XrmOptionDescRec emacs_options
[] = {
11582 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
11583 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
11585 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11586 XrmoptionSepArg
, NULL
},
11587 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
11589 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11590 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11591 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
11592 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
11593 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
11594 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
11595 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
11598 /* Whether atimer for Xt timeouts is activated or not. */
11600 static bool x_timeout_atimer_activated_flag
;
11602 #endif /* USE_X_TOOLKIT */
11604 static int x_initialized
;
11606 /* Test whether two display-name strings agree up to the dot that separates
11607 the screen number from the server number. */
11609 same_x_server (const char *name1
, const char *name2
)
11611 bool seen_colon
= false;
11612 Lisp_Object sysname
= Fsystem_name ();
11613 const char *system_name
= SSDATA (sysname
);
11614 ptrdiff_t system_name_length
= SBYTES (sysname
);
11615 ptrdiff_t length_until_period
= 0;
11617 while (system_name
[length_until_period
] != 0
11618 && system_name
[length_until_period
] != '.')
11619 length_until_period
++;
11621 /* Treat `unix' like an empty host name. */
11622 if (! strncmp (name1
, "unix:", 5))
11624 if (! strncmp (name2
, "unix:", 5))
11626 /* Treat this host's name like an empty host name. */
11627 if (! strncmp (name1
, system_name
, system_name_length
)
11628 && name1
[system_name_length
] == ':')
11629 name1
+= system_name_length
;
11630 if (! strncmp (name2
, system_name
, system_name_length
)
11631 && name2
[system_name_length
] == ':')
11632 name2
+= system_name_length
;
11633 /* Treat this host's domainless name like an empty host name. */
11634 if (! strncmp (name1
, system_name
, length_until_period
)
11635 && name1
[length_until_period
] == ':')
11636 name1
+= length_until_period
;
11637 if (! strncmp (name2
, system_name
, length_until_period
)
11638 && name2
[length_until_period
] == ':')
11639 name2
+= length_until_period
;
11641 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
11645 if (seen_colon
&& *name1
== '.')
11649 && (*name1
== '.' || *name1
== '\0')
11650 && (*name2
== '.' || *name2
== '\0'));
11653 /* Count number of set bits in mask and number of bits to shift to
11654 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
11657 get_bits_and_offset (unsigned long mask
, int *bits
, int *offset
)
11662 while (!(mask
& 1))
11678 /* Return true iff display DISPLAY is available for use.
11679 But don't permanently open it, just test its availability. */
11682 x_display_ok (const char *display
)
11684 /* XOpenDisplay fails if it gets a signal. Block SIGIO which may arrive. */
11685 unrequest_sigio ();
11686 Display
*dpy
= XOpenDisplay (display
);
11690 XCloseDisplay (dpy
);
11696 my_log_handler (const gchar
*log_domain
, GLogLevelFlags log_level
,
11697 const gchar
*msg
, gpointer user_data
)
11699 if (!strstr (msg
, "g_set_prgname"))
11700 fprintf (stderr
, "%s-WARNING **: %s\n", log_domain
, msg
);
11704 /* Create invisible cursor on X display referred by DPYINFO. */
11707 make_invisible_cursor (struct x_display_info
*dpyinfo
)
11709 Display
*dpy
= dpyinfo
->display
;
11710 static char const no_data
[] = { 0 };
11715 x_catch_errors (dpy
);
11716 pix
= XCreateBitmapFromData (dpy
, dpyinfo
->root_window
, no_data
, 1, 1);
11717 if (! x_had_errors_p (dpy
) && pix
!= None
)
11721 col
.red
= col
.green
= col
.blue
= 0;
11722 col
.flags
= DoRed
| DoGreen
| DoBlue
;
11723 pixc
= XCreatePixmapCursor (dpy
, pix
, pix
, &col
, &col
, 0, 0);
11724 if (! x_had_errors_p (dpy
) && pixc
!= None
)
11726 XFreePixmap (dpy
, pix
);
11729 x_uncatch_errors ();
11734 /* True if DPY supports Xfixes extension >= 4. */
11737 x_probe_xfixes_extension (Display
*dpy
)
11741 return XFixesQueryVersion (dpy
, &major
, &minor
) && major
>= 4;
11744 #endif /* HAVE_XFIXES */
11747 /* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
11750 xfixes_toggle_visible_pointer (struct frame
*f
, bool invisible
)
11754 XFixesHideCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11756 XFixesShowCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11757 f
->pointer_invisible
= invisible
;
11760 #endif /* HAVE_XFIXES */
11763 /* Toggle mouse pointer visibility on frame F by using invisible cursor. */
11766 x_toggle_visible_pointer (struct frame
*f
, bool invisible
)
11768 eassert (FRAME_DISPLAY_INFO (f
)->invisible_cursor
!= 0);
11770 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11771 FRAME_DISPLAY_INFO (f
)->invisible_cursor
);
11773 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11774 f
->output_data
.x
->current_cursor
);
11775 f
->pointer_invisible
= invisible
;
11778 /* Setup pointer blanking, prefer Xfixes if available. */
11781 x_setup_pointer_blanking (struct x_display_info
*dpyinfo
)
11783 /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
11784 X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */
11785 if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo
->display
))
11786 dpyinfo
->toggle_visible_pointer
= xfixes_toggle_visible_pointer
;
11789 dpyinfo
->toggle_visible_pointer
= x_toggle_visible_pointer
;
11790 dpyinfo
->invisible_cursor
= make_invisible_cursor (dpyinfo
);
11794 /* Current X display connection identifier. Incremented for each next
11795 connection established. */
11796 static unsigned x_display_id
;
11798 /* Open a connection to X display DISPLAY_NAME, and return
11799 the structure that describes the open display.
11800 If we cannot contact the display, return null. */
11802 struct x_display_info
*
11803 x_term_init (Lisp_Object display_name
, char *xrm_option
, char *resource_name
)
11806 struct terminal
*terminal
;
11807 struct x_display_info
*dpyinfo
;
11810 xcb_connection_t
*xcb_conn
;
11815 if (!x_initialized
)
11821 if (! x_display_ok (SSDATA (display_name
)))
11822 error ("Display %s can't be opened", SSDATA (display_name
));
11826 #define NUM_ARGV 10
11828 char *argv
[NUM_ARGV
];
11829 char **argv2
= argv
;
11832 if (x_initialized
++ > 1)
11834 xg_display_open (SSDATA (display_name
), &dpy
);
11838 static char display_opt
[] = "--display";
11839 static char name_opt
[] = "--name";
11841 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
11845 argv
[argc
++] = initial_argv
[0];
11847 if (! NILP (display_name
))
11849 argv
[argc
++] = display_opt
;
11850 argv
[argc
++] = SSDATA (display_name
);
11853 argv
[argc
++] = name_opt
;
11854 argv
[argc
++] = resource_name
;
11856 XSetLocaleModifiers ("");
11858 /* Work around GLib bug that outputs a faulty warning. See
11859 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
11860 id
= g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING
| G_LOG_FLAG_FATAL
11861 | G_LOG_FLAG_RECURSION
, my_log_handler
, NULL
);
11863 /* NULL window -> events for all windows go to our function.
11864 Call before gtk_init so Gtk+ event filters comes after our. */
11865 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
11867 /* gtk_init does set_locale. Fix locale before and after. */
11869 unrequest_sigio (); /* See comment in x_display_ok. */
11870 gtk_init (&argc
, &argv2
);
11874 g_log_remove_handler ("GLib", id
);
11878 dpy
= DEFAULT_GDK_DISPLAY ();
11880 #if ! GTK_CHECK_VERSION (2, 90, 0)
11881 /* Load our own gtkrc if it exists. */
11883 const char *file
= "~/.emacs.d/gtkrc";
11884 Lisp_Object s
, abs_file
;
11886 s
= build_string (file
);
11887 abs_file
= Fexpand_file_name (s
, Qnil
);
11889 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
11890 gtk_rc_parse (SSDATA (abs_file
));
11894 XSetErrorHandler (x_error_handler
);
11895 XSetIOErrorHandler (x_io_error_quitter
);
11898 #else /* not USE_GTK */
11899 #ifdef USE_X_TOOLKIT
11900 /* weiner@footloose.sps.mot.com reports that this causes
11902 X protocol error: BadAtom (invalid Atom parameter)
11903 on protocol request 18skiloaf.
11904 So let's not use it until R6. */
11905 #ifdef HAVE_X11XTR6
11906 XtSetLanguageProc (NULL
, NULL
, NULL
);
11917 argv
[argc
++] = "-xrm";
11918 argv
[argc
++] = xrm_option
;
11920 turn_on_atimers (false);
11921 unrequest_sigio (); /* See comment in x_display_ok. */
11922 dpy
= XtOpenDisplay (Xt_app_con
, SSDATA (display_name
),
11923 resource_name
, EMACS_CLASS
,
11924 emacs_options
, XtNumber (emacs_options
),
11927 turn_on_atimers (true);
11929 #ifdef HAVE_X11XTR6
11930 /* I think this is to compensate for XtSetLanguageProc. */
11935 #else /* not USE_X_TOOLKIT */
11936 XSetLocaleModifiers ("");
11937 unrequest_sigio (); // See comment in x_display_ok.
11938 dpy
= XOpenDisplay (SSDATA (display_name
));
11940 #endif /* not USE_X_TOOLKIT */
11941 #endif /* not USE_GTK*/
11943 /* Detect failure. */
11951 xcb_conn
= XGetXCBConnection (dpy
);
11955 xg_display_close (dpy
);
11957 #ifdef USE_X_TOOLKIT
11958 XtCloseDisplay (dpy
);
11960 XCloseDisplay (dpy
);
11962 #endif /* ! USE_GTK */
11969 /* We have definitely succeeded. Record the new connection. */
11971 dpyinfo
= xzalloc (sizeof *dpyinfo
);
11972 terminal
= x_create_terminal (dpyinfo
);
11975 struct x_display_info
*share
;
11977 for (share
= x_display_list
; share
; share
= share
->next
)
11978 if (same_x_server (SSDATA (XCAR (share
->name_list_element
)),
11979 SSDATA (display_name
)))
11982 terminal
->kboard
= share
->terminal
->kboard
;
11985 terminal
->kboard
= allocate_kboard (Qx
);
11987 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
11989 char *vendor
= ServerVendor (dpy
);
11991 /* Temporarily hide the partially initialized terminal. */
11992 terminal_list
= terminal
->next_terminal
;
11994 kset_system_key_alist
11996 call1 (Qvendor_specific_keysyms
,
11997 vendor
? build_string (vendor
) : empty_unibyte_string
));
11999 terminal
->next_terminal
= terminal_list
;
12000 terminal_list
= terminal
;
12003 /* Don't let the initial kboard remain current longer than necessary.
12004 That would cause problems if a file loaded on startup tries to
12005 prompt in the mini-buffer. */
12006 if (current_kboard
== initial_kboard
)
12007 current_kboard
= terminal
->kboard
;
12009 terminal
->kboard
->reference_count
++;
12012 /* Put this display on the chain. */
12013 dpyinfo
->next
= x_display_list
;
12014 x_display_list
= dpyinfo
;
12016 dpyinfo
->name_list_element
= Fcons (display_name
, Qnil
);
12017 dpyinfo
->display
= dpy
;
12018 dpyinfo
->connection
= ConnectionNumber (dpyinfo
->display
);
12020 dpyinfo
->xcb_connection
= xcb_conn
;
12023 /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
12024 dpyinfo
->smallest_font_height
= 1;
12025 dpyinfo
->smallest_char_width
= 1;
12027 /* Set the name of the terminal. */
12028 terminal
->name
= xlispstrdup (display_name
);
12031 XSetAfterFunction (x_current_display
, x_trace_wire
);
12034 Lisp_Object system_name
= Fsystem_name ();
12036 if (INT_ADD_WRAPV (SBYTES (Vinvocation_name
), SBYTES (system_name
) + 2,
12038 memory_full (SIZE_MAX
);
12039 dpyinfo
->x_id
= ++x_display_id
;
12040 dpyinfo
->x_id_name
= xmalloc (nbytes
);
12041 char *nametail
= lispstpcpy (dpyinfo
->x_id_name
, Vinvocation_name
);
12043 lispstpcpy (nametail
, system_name
);
12045 /* Figure out which modifier bits mean what. */
12046 x_find_modifier_meanings (dpyinfo
);
12048 /* Get the scroll bar cursor. */
12050 /* We must create a GTK cursor, it is required for GTK widgets. */
12051 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
12052 #endif /* USE_GTK */
12054 dpyinfo
->vertical_scroll_bar_cursor
12055 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12057 dpyinfo
->horizontal_scroll_bar_cursor
12058 = XCreateFontCursor (dpyinfo
->display
, XC_sb_h_double_arrow
);
12060 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12061 resource_name
, EMACS_CLASS
);
12062 #ifdef HAVE_XRMSETDATABASE
12063 XrmSetDatabase (dpyinfo
->display
, xrdb
);
12065 dpyinfo
->display
->db
= xrdb
;
12067 /* Put the rdb where we can find it in a way that works on
12069 dpyinfo
->xrdb
= xrdb
;
12071 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
12072 DefaultScreen (dpyinfo
->display
));
12073 select_visual (dpyinfo
);
12074 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
12075 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
12076 dpyinfo
->icon_bitmap_id
= -1;
12077 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
12079 reset_mouse_highlight (&dpyinfo
->mouse_highlight
);
12081 /* See if we can construct pixel values from RGB values. */
12082 if (dpyinfo
->visual
->class == TrueColor
)
12084 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
12085 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
12086 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
12087 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
12088 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
12089 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
12092 /* See if a private colormap is requested. */
12093 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
12095 if (dpyinfo
->visual
->class == PseudoColor
)
12097 AUTO_STRING (privateColormap
, "privateColormap");
12098 AUTO_STRING (PrivateColormap
, "PrivateColormap");
12100 = display_x_get_resource (dpyinfo
, privateColormap
,
12101 PrivateColormap
, Qnil
, Qnil
);
12102 if (STRINGP (value
)
12103 && (!strcmp (SSDATA (value
), "true")
12104 || !strcmp (SSDATA (value
), "on")))
12105 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
12109 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
12110 dpyinfo
->visual
, AllocNone
);
12114 /* If we are using Xft, the following precautions should be made:
12116 1. Make sure that the Xrender extension is added before the Xft one.
12117 Otherwise, the close-display hook set by Xft is called after the one
12118 for Xrender, and the former tries to re-add the latter. This results
12119 in inconsistency of internal states and leads to X protocol error when
12120 one reconnects to the same X server (Bug#1696).
12122 2. Check dpi value in X resources. It is better we use it as well,
12123 since Xft will use it, as will all Gnome applications. If our real DPI
12124 is smaller or larger than the one Xft uses, our font will look smaller
12125 or larger than other for other applications, even if it is the same
12126 font name (monospace-10 for example). */
12128 int event_base
, error_base
;
12132 XRenderQueryExtension (dpyinfo
->display
, &event_base
, &error_base
);
12134 v
= XGetDefault (dpyinfo
->display
, "Xft", "dpi");
12135 if (v
!= NULL
&& sscanf (v
, "%lf", &d
) == 1)
12136 dpyinfo
->resy
= dpyinfo
->resx
= d
;
12140 if (dpyinfo
->resy
< 1)
12142 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
12143 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
12144 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
12145 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
12146 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
12147 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
12148 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
12149 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
12150 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
12154 static const struct
12159 #define ATOM_REFS_INIT(string, member) \
12160 { string, offsetof (struct x_display_info, member) },
12161 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols
)
12162 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus
)
12163 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself
)
12164 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window
)
12165 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state
)
12166 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied
)
12167 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved
)
12168 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader
)
12169 ATOM_REFS_INIT ("Editres", Xatom_editres
)
12170 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD
)
12171 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP
)
12172 ATOM_REFS_INIT ("TEXT", Xatom_TEXT
)
12173 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT
)
12174 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING
)
12175 ATOM_REFS_INIT ("DELETE", Xatom_DELETE
)
12176 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE
)
12177 ATOM_REFS_INIT ("INCR", Xatom_INCR
)
12178 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP
)
12179 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS
)
12180 ATOM_REFS_INIT ("NULL", Xatom_NULL
)
12181 ATOM_REFS_INIT ("ATOM", Xatom_ATOM
)
12182 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR
)
12183 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER
)
12184 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO
)
12185 /* For properties of font. */
12186 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE
)
12187 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH
)
12188 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET
)
12189 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE
)
12190 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT
)
12191 /* Ghostscript support. */
12192 ATOM_REFS_INIT ("DONE", Xatom_DONE
)
12193 ATOM_REFS_INIT ("PAGE", Xatom_PAGE
)
12194 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar
)
12195 ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar
)
12196 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED
)
12198 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state
)
12199 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen
)
12200 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
12201 Xatom_net_wm_state_maximized_horz
)
12202 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
12203 Xatom_net_wm_state_maximized_vert
)
12204 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky
)
12205 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden
)
12206 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type
)
12207 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
12208 Xatom_net_window_type_tooltip
)
12209 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name
)
12210 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name
)
12211 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported
)
12212 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check
)
12213 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity
)
12214 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window
)
12215 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents
)
12216 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop
)
12217 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea
)
12218 /* Session management */
12219 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID
)
12220 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop
)
12221 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr
)
12225 enum { atom_count
= ARRAYELTS (atom_refs
) };
12226 /* 1 for _XSETTINGS_SN. */
12227 enum { total_atom_count
= 1 + atom_count
};
12228 Atom atoms_return
[total_atom_count
];
12229 char *atom_names
[total_atom_count
];
12230 static char const xsettings_fmt
[] = "_XSETTINGS_S%d";
12231 char xsettings_atom_name
[sizeof xsettings_fmt
- 2
12232 + INT_STRLEN_BOUND (int)];
12234 for (i
= 0; i
< atom_count
; i
++)
12235 atom_names
[i
] = (char *) atom_refs
[i
].name
;
12237 /* Build _XSETTINGS_SN atom name. */
12238 sprintf (xsettings_atom_name
, xsettings_fmt
,
12239 XScreenNumberOfScreen (dpyinfo
->screen
));
12240 atom_names
[i
] = xsettings_atom_name
;
12242 XInternAtoms (dpyinfo
->display
, atom_names
, total_atom_count
,
12243 False
, atoms_return
);
12245 for (i
= 0; i
< atom_count
; i
++)
12246 *(Atom
*) ((char *) dpyinfo
+ atom_refs
[i
].offset
) = atoms_return
[i
];
12248 /* Manually copy last atom. */
12249 dpyinfo
->Xatom_xsettings_sel
= atoms_return
[i
];
12252 dpyinfo
->x_dnd_atoms_size
= 8;
12253 dpyinfo
->x_dnd_atoms
= xmalloc (sizeof *dpyinfo
->x_dnd_atoms
12254 * dpyinfo
->x_dnd_atoms_size
);
12256 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12257 gray_bits
, gray_width
, gray_height
,
12260 x_setup_pointer_blanking (dpyinfo
);
12263 xim_initialize (dpyinfo
, resource_name
);
12266 xsettings_initialize (dpyinfo
);
12268 /* This is only needed for distinguishing keyboard and process input. */
12269 if (dpyinfo
->connection
!= 0)
12270 add_keyboard_wait_descriptor (dpyinfo
->connection
);
12273 fcntl (dpyinfo
->connection
, F_SETOWN
, getpid ());
12274 #endif /* ! defined (F_SETOWN) */
12276 if (interrupt_input
)
12277 init_sigio (dpyinfo
->connection
);
12281 XrmValue d
, fr
, to
;
12284 dpy
= dpyinfo
->display
;
12285 d
.addr
= (XPointer
)&dpy
;
12286 d
.size
= sizeof (Display
*);
12287 fr
.addr
= XtDefaultFont
;
12288 fr
.size
= sizeof (XtDefaultFont
);
12289 to
.size
= sizeof (Font
*);
12290 to
.addr
= (XPointer
)&font
;
12291 x_catch_errors (dpy
);
12292 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
12294 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
12295 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
12296 /* Do not free XFontStruct returned by the above call to XQueryFont.
12297 This leads to X protocol errors at XtCloseDisplay (Bug#18403). */
12298 x_uncatch_errors ();
12302 /* See if we should run in synchronous mode. This is useful
12303 for debugging X code. */
12305 AUTO_STRING (synchronous
, "synchronous");
12306 AUTO_STRING (Synchronous
, "Synchronous");
12307 Lisp_Object value
= display_x_get_resource (dpyinfo
, synchronous
,
12308 Synchronous
, Qnil
, Qnil
);
12309 if (STRINGP (value
)
12310 && (!strcmp (SSDATA (value
), "true")
12311 || !strcmp (SSDATA (value
), "on")))
12312 XSynchronize (dpyinfo
->display
, True
);
12316 AUTO_STRING (useXIM
, "useXIM");
12317 AUTO_STRING (UseXIM
, "UseXIM");
12318 Lisp_Object value
= display_x_get_resource (dpyinfo
, useXIM
, UseXIM
,
12321 if (STRINGP (value
)
12322 && (!strcmp (SSDATA (value
), "false")
12323 || !strcmp (SSDATA (value
), "off")))
12326 if (STRINGP (value
)
12327 && (!strcmp (SSDATA (value
), "true")
12328 || !strcmp (SSDATA (value
), "on")))
12334 /* Only do this for the very first display in the Emacs session.
12335 Ignore X session management when Emacs was first started on a
12336 tty or started as a daemon. */
12337 if (terminal
->id
== 1 && ! IS_DAEMON
)
12338 x_session_initialize (dpyinfo
);
12342 x_extension_initialize (dpyinfo
);
12350 /* Get rid of display DPYINFO, deleting all frames on it,
12351 and without sending any more commands to the X server. */
12354 x_delete_display (struct x_display_info
*dpyinfo
)
12356 struct terminal
*t
;
12357 struct color_name_cache_entry
*color_entry
, *next_color_entry
;
12359 /* Close all frames and delete the generic struct terminal for this
12361 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
12362 if (t
->type
== output_x_window
&& t
->display_info
.x
== dpyinfo
)
12365 /* Close X session management when we close its display. */
12366 if (t
->id
== 1 && x_session_have_connection ())
12367 x_session_close ();
12369 delete_terminal (t
);
12373 if (next_noop_dpyinfo
== dpyinfo
)
12374 next_noop_dpyinfo
= dpyinfo
->next
;
12376 if (x_display_list
== dpyinfo
)
12377 x_display_list
= dpyinfo
->next
;
12380 struct x_display_info
*tail
;
12382 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12383 if (tail
->next
== dpyinfo
)
12384 tail
->next
= tail
->next
->next
;
12387 for (color_entry
= dpyinfo
->color_names
;
12389 color_entry
= next_color_entry
)
12391 next_color_entry
= color_entry
->next
;
12392 xfree (color_entry
->name
);
12393 xfree (color_entry
);
12396 xfree (dpyinfo
->x_id_name
);
12397 xfree (dpyinfo
->x_dnd_atoms
);
12398 xfree (dpyinfo
->color_cells
);
12402 #ifdef USE_X_TOOLKIT
12404 /* Atimer callback function for TIMER. Called every 0.1s to process
12405 Xt timeouts, if needed. We must avoid calling XtAppPending as
12406 much as possible because that function does an implicit XFlush
12407 that slows us down. */
12410 x_process_timeouts (struct atimer
*timer
)
12413 x_timeout_atimer_activated_flag
= false;
12414 if (toolkit_scroll_bar_interaction
|| popup_activated ())
12416 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
12417 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
12418 /* Reactivate the atimer for next time. */
12419 x_activate_timeout_atimer ();
12424 /* Install an asynchronous timer that processes Xt timeout events
12425 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
12426 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
12427 function whenever these variables are set. This is necessary
12428 because some widget sets use timeouts internally, for example the
12429 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
12430 processed, these widgets don't behave normally. */
12433 x_activate_timeout_atimer (void)
12436 if (!x_timeout_atimer_activated_flag
)
12438 struct timespec interval
= make_timespec (0, 100 * 1000 * 1000);
12439 start_atimer (ATIMER_RELATIVE
, interval
, x_process_timeouts
, 0);
12440 x_timeout_atimer_activated_flag
= true;
12445 #endif /* USE_X_TOOLKIT */
12448 /* Set up use of X before we make the first connection. */
12450 static struct redisplay_interface x_redisplay_interface
=
12452 x_frame_parm_handlers
,
12456 x_clear_end_of_line
,
12458 x_after_update_window_line
,
12459 x_update_window_begin
,
12460 x_update_window_end
,
12462 x_clear_window_mouse_face
,
12463 x_get_glyph_overhangs
,
12464 x_fix_overlapping_area
,
12465 x_draw_fringe_bitmap
,
12467 x_cr_define_fringe_bitmap
,
12468 x_cr_destroy_fringe_bitmap
,
12470 0, /* define_fringe_bitmap */
12471 0, /* destroy_fringe_bitmap */
12473 x_compute_glyph_string_overhangs
,
12474 x_draw_glyph_string
,
12475 x_define_frame_cursor
,
12476 x_clear_frame_area
,
12477 x_draw_window_cursor
,
12478 x_draw_vertical_window_border
,
12479 x_draw_window_divider
,
12480 x_shift_glyphs_for_insert
, /* Never called; see comment in function. */
12486 /* This function is called when the last frame on a display is deleted. */
12488 x_delete_terminal (struct terminal
*terminal
)
12490 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
12492 /* Protect against recursive calls. delete_frame in
12493 delete_terminal calls us back when it deletes our last frame. */
12494 if (!terminal
->name
)
12499 /* We must close our connection to the XIM server before closing the
12502 xim_close_dpy (dpyinfo
);
12505 /* Normally, the display is available... */
12506 if (dpyinfo
->display
)
12508 x_destroy_all_bitmaps (dpyinfo
);
12509 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
12511 /* Whether or not XCloseDisplay destroys the associated resource
12512 database depends on the version of libX11. To avoid both
12513 crash and memory leak, we dissociate the database from the
12514 display and then destroy dpyinfo->xrdb ourselves.
12516 Unfortunately, the above strategy does not work in some
12517 situations due to a bug in newer versions of libX11: because
12518 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
12519 dpy->db is NULL, XCloseDisplay destroys the associated
12520 database whereas it has not been created by XGetDefault
12521 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
12522 don't destroy the database here in order to avoid the crash
12523 in the above situations for now, though that may cause memory
12524 leaks in other situations. */
12526 #ifdef HAVE_XRMSETDATABASE
12527 XrmSetDatabase (dpyinfo
->display
, NULL
);
12529 dpyinfo
->display
->db
= NULL
;
12531 /* We used to call XrmDestroyDatabase from x_delete_display, but
12532 some older versions of libX11 crash if we call it after
12533 closing all the displays. */
12534 XrmDestroyDatabase (dpyinfo
->xrdb
);
12538 xg_display_close (dpyinfo
->display
);
12540 #ifdef USE_X_TOOLKIT
12541 XtCloseDisplay (dpyinfo
->display
);
12543 XCloseDisplay (dpyinfo
->display
);
12545 #endif /* ! USE_GTK */
12546 /* Do not close the connection here because it's already closed
12547 by X(t)CloseDisplay (Bug#18403). */
12548 dpyinfo
->display
= NULL
;
12551 /* ...but if called from x_connection_closed, the display may already
12552 be closed and dpyinfo->display was set to 0 to indicate that. Since
12553 X server is most likely gone, explicit close is the only reliable
12554 way to continue and avoid Bug#19147. */
12555 else if (dpyinfo
->connection
>= 0)
12556 emacs_close (dpyinfo
->connection
);
12558 /* No more input on this descriptor. */
12559 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
12560 /* Mark as dead. */
12561 dpyinfo
->connection
= -1;
12563 x_delete_display (dpyinfo
);
12567 /* Create a struct terminal, initialize it with the X11 specific
12568 functions and make DISPLAY->TERMINAL point to it. */
12570 static struct terminal
*
12571 x_create_terminal (struct x_display_info
*dpyinfo
)
12573 struct terminal
*terminal
;
12575 terminal
= create_terminal (output_x_window
, &x_redisplay_interface
);
12577 terminal
->display_info
.x
= dpyinfo
;
12578 dpyinfo
->terminal
= terminal
;
12580 /* kboard is initialized in x_term_init. */
12582 terminal
->clear_frame_hook
= x_clear_frame
;
12583 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
12584 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
12585 terminal
->ring_bell_hook
= XTring_bell
;
12586 terminal
->toggle_invisible_pointer_hook
= XTtoggle_invisible_pointer
;
12587 terminal
->update_begin_hook
= x_update_begin
;
12588 terminal
->update_end_hook
= x_update_end
;
12589 terminal
->read_socket_hook
= XTread_socket
;
12590 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
12591 terminal
->mouse_position_hook
= XTmouse_position
;
12592 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
12593 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
12594 terminal
->fullscreen_hook
= XTfullscreen_hook
;
12595 terminal
->menu_show_hook
= x_menu_show
;
12596 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
12597 terminal
->popup_dialog_hook
= xw_popup_dialog
;
12599 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12600 terminal
->set_horizontal_scroll_bar_hook
= XTset_horizontal_scroll_bar
;
12601 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12602 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12603 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12604 terminal
->delete_frame_hook
= x_destroy_window
;
12605 terminal
->delete_terminal_hook
= x_delete_terminal
;
12606 /* Other hooks are NULL by default. */
12612 x_initialize (void)
12617 any_help_event_p
= false;
12618 ignore_next_mouse_click_timeout
= 0;
12621 current_count
= -1;
12624 /* Try to use interrupt input; if we can't, then start polling. */
12625 Fset_input_interrupt_mode (Qt
);
12627 #ifdef USE_X_TOOLKIT
12628 XtToolkitInitialize ();
12630 Xt_app_con
= XtCreateApplicationContext ();
12632 /* Register a converter from strings to pixels, which uses
12633 Emacs' color allocation infrastructure. */
12634 XtAppSetTypeConverter (Xt_app_con
,
12635 XtRString
, XtRPixel
, cvt_string_to_pixel
,
12636 cvt_string_to_pixel_args
,
12637 XtNumber (cvt_string_to_pixel_args
),
12638 XtCacheByDisplay
, cvt_pixel_dtor
);
12640 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
12643 #ifdef USE_TOOLKIT_SCROLL_BARS
12645 xaw3d_arrow_scroll
= False
;
12646 xaw3d_pick_top
= True
;
12651 x_cr_init_fringe (&x_redisplay_interface
);
12654 /* Note that there is no real way portable across R3/R4 to get the
12655 original error handler. */
12656 XSetErrorHandler (x_error_handler
);
12657 XSetIOErrorHandler (x_io_error_quitter
);
12664 /* Emacs can handle only core input events, so make sure
12665 Gtk doesn't use Xinput or Xinput2 extensions. */
12666 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
12671 syms_of_xterm (void)
12673 x_error_message
= NULL
;
12675 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
12676 DEFSYM (Qlatin_1
, "latin-1");
12679 xg_default_icon_file
= build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
12680 staticpro (&xg_default_icon_file
);
12682 DEFSYM (Qx_gtk_map_stock
, "x-gtk-map-stock");
12685 DEFVAR_BOOL ("x-use-underline-position-properties",
12686 x_use_underline_position_properties
,
12687 doc
: /* Non-nil means make use of UNDERLINE_POSITION font properties.
12688 A value of nil means ignore them. If you encounter fonts with bogus
12689 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12690 to 4.1, set this to nil. You can also use `underline-minimum-offset'
12691 to override the font's UNDERLINE_POSITION for small font display
12693 x_use_underline_position_properties
= true;
12695 DEFVAR_BOOL ("x-underline-at-descent-line",
12696 x_underline_at_descent_line
,
12697 doc
: /* Non-nil means to draw the underline at the same place as the descent line.
12698 A value of nil means to draw the underline according to the value of the
12699 variable `x-use-underline-position-properties', which is usually at the
12700 baseline level. The default value is nil. */);
12701 x_underline_at_descent_line
= false;
12703 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
12704 x_mouse_click_focus_ignore_position
,
12705 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
12706 This variable is only used when the window manager requires that you
12707 click on a frame to select it (give it focus). In that case, a value
12708 of nil, means that the selected window and cursor position changes to
12709 reflect the mouse click position, while a non-nil value means that the
12710 selected window or cursor position is preserved. */);
12711 x_mouse_click_focus_ignore_position
= false;
12713 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars
,
12714 doc
: /* Which toolkit scroll bars Emacs uses, if any.
12715 A value of nil means Emacs doesn't use toolkit scroll bars.
12716 With the X Window system, the value is a symbol describing the
12717 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
12718 With MS Windows or Nextstep, the value is t. */);
12719 #ifdef USE_TOOLKIT_SCROLL_BARS
12721 Vx_toolkit_scroll_bars
= intern_c_string ("motif");
12722 #elif defined HAVE_XAW3D
12723 Vx_toolkit_scroll_bars
= intern_c_string ("xaw3d");
12725 Vx_toolkit_scroll_bars
= intern_c_string ("gtk");
12727 Vx_toolkit_scroll_bars
= intern_c_string ("xaw");
12730 Vx_toolkit_scroll_bars
= Qnil
;
12733 DEFSYM (Qmodifier_value
, "modifier-value");
12734 DEFSYM (Qalt
, "alt");
12735 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
12736 DEFSYM (Qhyper
, "hyper");
12737 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
12738 DEFSYM (Qmeta
, "meta");
12739 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
12740 DEFSYM (Qsuper
, "super");
12741 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
12743 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym
,
12744 doc
: /* Which keys Emacs uses for the alt modifier.
12745 This should be one of the symbols `alt', `hyper', `meta', `super'.
12746 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
12747 is nil, which is the same as `alt'. */);
12748 Vx_alt_keysym
= Qnil
;
12750 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym
,
12751 doc
: /* Which keys Emacs uses for the hyper modifier.
12752 This should be one of the symbols `alt', `hyper', `meta', `super'.
12753 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
12754 default is nil, which is the same as `hyper'. */);
12755 Vx_hyper_keysym
= Qnil
;
12757 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym
,
12758 doc
: /* Which keys Emacs uses for the meta modifier.
12759 This should be one of the symbols `alt', `hyper', `meta', `super'.
12760 For example, `meta' means use the Meta_L and Meta_R keysyms. The
12761 default is nil, which is the same as `meta'. */);
12762 Vx_meta_keysym
= Qnil
;
12764 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym
,
12765 doc
: /* Which keys Emacs uses for the super modifier.
12766 This should be one of the symbols `alt', `hyper', `meta', `super'.
12767 For example, `super' means use the Super_L and Super_R keysyms. The
12768 default is nil, which is the same as `super'. */);
12769 Vx_super_keysym
= Qnil
;
12771 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table
,
12772 doc
: /* Hash table of character codes indexed by X keysym codes. */);
12773 Vx_keysym_table
= make_hash_table (hashtest_eql
, make_number (900),
12774 make_float (DEFAULT_REHASH_SIZE
),
12775 make_float (DEFAULT_REHASH_THRESHOLD
),
12778 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
12779 x_frame_normalize_before_maximize
,
12780 doc
: /* Non-nil means normalize frame before maximizing.
12781 If this variable is t, Emacs first asks the window manager to give the
12782 frame its normal size, and only then the final state, whenever changing
12783 from a full-height, full-width or full-both state to the maximized one
12784 or when changing from the maximized to the full-height or full-width
12787 Set this variable only if your window manager cannot handle the
12788 transition between the various maximization states. */);
12789 x_frame_normalize_before_maximize
= false;