1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
3 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 2, or (at your option)
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; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
59 #ifndef INCLUDED_FCNTL
66 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
67 /* #include <sys/param.h> */
73 #include "dispextern.h"
75 #include "termhooks.h"
83 #include "intervals.h"
89 #include <X11/Shell.h>
92 #ifdef HAVE_SYS_TIME_H
104 extern int xlwmenu_window_p
P_ ((Widget w
, Window window
));
105 extern void xlwmenu_redisplay
P_ ((Widget
));
108 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
110 extern void free_frame_menubar
P_ ((struct frame
*));
111 extern struct frame
*x_menubar_window_to_frame
P_ ((struct x_display_info
*,
116 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
118 extern void _XEditResCheckMessages ();
119 #endif /* not NO_EDITRES */
121 /* Include toolkit specific headers for the scroll bar widget. */
123 #ifdef USE_TOOLKIT_SCROLL_BARS
124 #if defined USE_MOTIF
125 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
126 #include <Xm/ScrollBar.h>
127 #else /* !USE_MOTIF i.e. use Xaw */
130 #include <X11/Xaw3d/Simple.h>
131 #include <X11/Xaw3d/Scrollbar.h>
132 #define ARROW_SCROLLBAR
133 #define XAW_ARROW_SCROLLBARS
134 #include <X11/Xaw3d/ScrollbarP.h>
135 #else /* !HAVE_XAW3D */
136 #include <X11/Xaw/Simple.h>
137 #include <X11/Xaw/Scrollbar.h>
138 #endif /* !HAVE_XAW3D */
140 #define XtNpickTop "pickTop"
141 #endif /* !XtNpickTop */
142 #endif /* !USE_MOTIF */
143 #endif /* USE_TOOLKIT_SCROLL_BARS */
145 #endif /* USE_X_TOOLKIT */
147 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
148 #define x_any_window_to_frame x_window_to_frame
149 #define x_top_window_to_frame x_window_to_frame
154 #ifndef XtNinitialState
155 #define XtNinitialState "initialState"
159 #define abs(x) ((x) < 0 ? -(x) : (x))
161 /* Default to using XIM if available. */
165 int use_xim
= 0; /* configure --without-xim */
170 /* Non-nil means Emacs uses toolkit scroll bars. */
172 Lisp_Object Vx_toolkit_scroll_bars
;
174 /* Non-zero means that a HELP_EVENT has been generated since Emacs
177 static int any_help_event_p
;
179 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
180 static Lisp_Object last_window
;
182 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
184 int x_use_underline_position_properties
;
186 /* This is a chain of structures for all the X displays currently in
189 struct x_display_info
*x_display_list
;
191 /* This is a list of cons cells, each of the form (NAME
192 . FONT-LIST-CACHE), one for each element of x_display_list and in
193 the same order. NAME is the name of the frame. FONT-LIST-CACHE
194 records previous values returned by x-list-fonts. */
196 Lisp_Object x_display_name_list
;
198 /* Frame being updated by update_frame. This is declared in term.c.
199 This is set by update_begin and looked at by all the XT functions.
200 It is zero while not inside an update. In that case, the XT
201 functions assume that `selected_frame' is the frame to apply to. */
203 extern struct frame
*updating_frame
;
205 /* This is a frame waiting to be auto-raised, within XTread_socket. */
207 struct frame
*pending_autoraise_frame
;
210 /* The application context for Xt use. */
211 XtAppContext Xt_app_con
;
212 static String Xt_default_resources
[] = {0};
213 #endif /* USE_X_TOOLKIT */
215 /* Non-zero means user is interacting with a toolkit scroll bar. */
217 static int toolkit_scroll_bar_interaction
;
219 /* Non-zero means to not move point as a result of clicking on a
220 frame to focus it (when focus-follows-mouse is nil). */
222 int x_mouse_click_focus_ignore_position
;
224 /* Non-zero timeout value means ignore next mouse click if it arrives
225 before that timeout elapses (i.e. as part of the same sequence of
226 events resulting from clicking on a frame to select it). */
228 static unsigned long ignore_next_mouse_click_timeout
;
232 Formerly, we used PointerMotionHintMask (in standard_event_mask)
233 so that we would have to call XQueryPointer after each MotionNotify
234 event to ask for another such event. However, this made mouse tracking
235 slow, and there was a bug that made it eventually stop.
237 Simply asking for MotionNotify all the time seems to work better.
239 In order to avoid asking for motion events and then throwing most
240 of them away or busy-polling the server for mouse positions, we ask
241 the server for pointer motion hints. This means that we get only
242 one event per group of mouse movements. "Groups" are delimited by
243 other kinds of events (focus changes and button clicks, for
244 example), or by XQueryPointer calls; when one of these happens, we
245 get another MotionNotify event the next time the mouse moves. This
246 is at least as efficient as getting motion events when mouse
247 tracking is on, and I suspect only negligibly worse when tracking
250 /* Where the mouse was last time we reported a mouse event. */
252 static XRectangle last_mouse_glyph
;
253 static Lisp_Object last_mouse_press_frame
;
255 /* The scroll bar in which the last X motion event occurred.
257 If the last X motion event occurred in a scroll bar, we set this so
258 XTmouse_position can know whether to report a scroll bar motion or
261 If the last X motion event didn't occur in a scroll bar, we set
262 this to Qnil, to tell XTmouse_position to return an ordinary motion
265 static Lisp_Object last_mouse_scroll_bar
;
267 /* This is a hack. We would really prefer that XTmouse_position would
268 return the time associated with the position it returns, but there
269 doesn't seem to be any way to wrest the time-stamp from the server
270 along with the position query. So, we just keep track of the time
271 of the last movement we received, and return that in hopes that
272 it's somewhat accurate. */
274 static Time last_mouse_movement_time
;
276 /* Incremented by XTread_socket whenever it really tries to read
280 static int volatile input_signal_count
;
282 static int input_signal_count
;
285 /* Used locally within XTread_socket. */
287 static int x_noop_count
;
289 /* Initial values of argv and argc. */
291 extern char **initial_argv
;
292 extern int initial_argc
;
294 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
296 /* Tells if a window manager is present or not. */
298 extern Lisp_Object Vx_no_window_manager
;
300 extern Lisp_Object Qeql
;
304 /* A mask of extra modifier bits to put into every keyboard char. */
306 extern EMACS_INT extra_keyboard_modifiers
;
308 /* The keysyms to use for the various modifiers. */
310 Lisp_Object Vx_alt_keysym
, Vx_hyper_keysym
, Vx_meta_keysym
, Vx_super_keysym
;
311 Lisp_Object Vx_keysym_table
;
312 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
314 static Lisp_Object Qvendor_specific_keysyms
;
315 static Lisp_Object Qlatin_1
;
317 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
318 extern int x_bitmap_mask
P_ ((FRAME_PTR
, int));
320 static int x_alloc_nearest_color_1
P_ ((Display
*, Colormap
, XColor
*));
321 static void x_set_window_size_1
P_ ((struct frame
*, int, int, int));
322 static const XColor
*x_color_cells
P_ ((Display
*, int *));
323 static void x_update_window_end
P_ ((struct window
*, int, int));
324 void x_delete_display
P_ ((struct x_display_info
*));
325 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
327 static int x_io_error_quitter
P_ ((Display
*));
328 int x_catch_errors
P_ ((Display
*));
329 void x_uncatch_errors
P_ ((Display
*, int));
330 void x_lower_frame
P_ ((struct frame
*));
331 void x_scroll_bar_clear
P_ ((struct frame
*));
332 int x_had_errors_p
P_ ((Display
*));
333 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
334 void x_raise_frame
P_ ((struct frame
*));
335 void x_set_window_size
P_ ((struct frame
*, int, int, int));
336 void x_wm_set_window_state
P_ ((struct frame
*, int));
337 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
338 struct display
*x_create_frame_display
P_ ((struct x_display_info
*));
339 void x_delete_frame_display
P_ ((struct display
*));
340 void x_initialize
P_ ((void));
341 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
342 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
343 static void x_update_end
P_ ((struct frame
*));
344 static void XTframe_up_to_date
P_ ((struct frame
*));
345 static void XTset_terminal_modes
P_ ((struct display
*));
346 static void XTreset_terminal_modes
P_ ((struct display
*));
347 static void x_clear_frame
P_ ((struct frame
*));
348 static void frame_highlight
P_ ((struct frame
*));
349 static void frame_unhighlight
P_ ((struct frame
*));
350 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
351 static void x_focus_changed
P_ ((int, int, struct x_display_info
*,
352 struct frame
*, struct input_event
*));
353 static void x_detect_focus_change
P_ ((struct x_display_info
*,
354 XEvent
*, struct input_event
*));
355 static void XTframe_rehighlight
P_ ((struct frame
*));
356 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
357 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
358 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
359 enum text_cursor_kinds
));
361 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, GC
));
362 static void x_flush
P_ ((struct frame
*f
));
363 static void x_update_begin
P_ ((struct frame
*));
364 static void x_update_window_begin
P_ ((struct window
*));
365 static void x_after_update_window_line
P_ ((struct glyph_row
*));
366 static struct scroll_bar
*x_window_to_scroll_bar
P_ ((Display
*, Window
));
367 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
368 enum scroll_bar_part
*,
369 Lisp_Object
*, Lisp_Object
*,
371 static void x_check_fullscreen
P_ ((struct frame
*));
372 static void x_check_expected_move
P_ ((struct frame
*));
373 static int handle_one_xevent
P_ ((struct x_display_info
*, XEvent
*,
374 int *, struct input_event
*));
377 /* Flush display of frame F, or of all frames if F is null. */
386 Lisp_Object rest
, frame
;
387 FOR_EACH_FRAME (rest
, frame
)
388 if (FRAME_X_P (XFRAME (frame
)))
389 x_flush (XFRAME (frame
));
391 else if (FRAME_X_P (f
))
392 XFlush (FRAME_X_DISPLAY (f
));
397 /* Remove calls to XFlush by defining XFlush to an empty replacement.
398 Calls to XFlush should be unnecessary because the X output buffer
399 is flushed automatically as needed by calls to XPending,
400 XNextEvent, or XWindowEvent according to the XFlush man page.
401 XTread_socket calls XPending. Removing XFlush improves
404 #define XFlush(DISPLAY) (void) 0
407 /***********************************************************************
409 ***********************************************************************/
413 /* This is a function useful for recording debugging information about
414 the sequence of occurrences in this file. */
422 struct record event_record
[100];
424 int event_record_index
;
426 record_event (locus
, type
)
430 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
431 event_record_index
= 0;
433 event_record
[event_record_index
].locus
= locus
;
434 event_record
[event_record_index
].type
= type
;
435 event_record_index
++;
442 /* Return the struct x_display_info corresponding to DPY. */
444 struct x_display_info
*
445 x_display_info_for_display (dpy
)
448 struct x_display_info
*dpyinfo
;
450 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
451 if (dpyinfo
->display
== dpy
)
459 /***********************************************************************
460 Starting and ending an update
461 ***********************************************************************/
463 /* Start an update of frame F. This function is installed as a hook
464 for update_begin, i.e. it is called when update_begin is called.
465 This function is called prior to calls to x_update_window_begin for
466 each window being updated. Currently, there is nothing to do here
467 because all interesting stuff is done on a window basis. */
476 /* Start update of window W. Set the global variable updated_window
477 to the window being updated and set output_cursor to the cursor
481 x_update_window_begin (w
)
484 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
485 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
488 set_output_cursor (&w
->cursor
);
492 if (f
== display_info
->mouse_face_mouse_frame
)
494 /* Don't do highlighting for mouse motion during the update. */
495 display_info
->mouse_face_defer
= 1;
497 /* If F needs to be redrawn, simply forget about any prior mouse
499 if (FRAME_GARBAGED_P (f
))
500 display_info
->mouse_face_window
= Qnil
;
502 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
503 their mouse_face_p flag set, which means that they are always
504 unequal to rows in a desired matrix which never have that
505 flag set. So, rows containing mouse-face glyphs are never
506 scrolled, and we don't have to switch the mouse highlight off
507 here to prevent it from being scrolled. */
509 /* Can we tell that this update does not affect the window
510 where the mouse highlight is? If so, no need to turn off.
511 Likewise, don't do anything if the frame is garbaged;
512 in that case, the frame's current matrix that we would use
513 is all wrong, and we will redisplay that line anyway. */
514 if (!NILP (display_info
->mouse_face_window
)
515 && w
== XWINDOW (display_info
->mouse_face_window
))
519 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
520 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
523 if (i
< w
->desired_matrix
->nrows
)
524 clear_mouse_face (display_info
);
533 /* Draw a vertical window border from (x,y0) to (x,y1) */
536 x_draw_vertical_window_border (w
, x
, y0
, y1
)
540 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
542 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
543 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
546 /* End update of window W (which is equal to updated_window).
548 Draw vertical borders between horizontally adjacent windows, and
549 display W's cursor if CURSOR_ON_P is non-zero.
551 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
552 glyphs in mouse-face were overwritten. In that case we have to
553 make sure that the mouse-highlight is properly redrawn.
555 W may be a menu bar pseudo-window in case we don't have X toolkit
556 support. Such windows don't have a cursor, so don't display it
560 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
562 int cursor_on_p
, mouse_face_overwritten_p
;
564 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (w
->frame
));
566 if (!w
->pseudo_window_p
)
571 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
573 output_cursor
.x
, output_cursor
.y
);
575 x_draw_vertical_border (w
);
577 draw_window_fringes (w
);
582 /* If a row with mouse-face was overwritten, arrange for
583 XTframe_up_to_date to redisplay the mouse highlight. */
584 if (mouse_face_overwritten_p
)
586 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
587 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
588 dpyinfo
->mouse_face_window
= Qnil
;
591 updated_window
= NULL
;
595 /* End update of frame F. This function is installed as a hook in
602 /* Mouse highlight may be displayed again. */
603 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
607 XFlush (FRAME_X_DISPLAY (f
));
613 /* This function is called from various places in xdisp.c whenever a
614 complete update has been performed. The global variable
615 updated_window is not available here. */
618 XTframe_up_to_date (f
)
623 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
625 if (dpyinfo
->mouse_face_deferred_gc
626 || f
== dpyinfo
->mouse_face_mouse_frame
)
629 if (dpyinfo
->mouse_face_mouse_frame
)
630 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
631 dpyinfo
->mouse_face_mouse_x
,
632 dpyinfo
->mouse_face_mouse_y
);
633 dpyinfo
->mouse_face_deferred_gc
= 0;
640 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
641 arrow bitmaps, or clear the fringes if no bitmaps are required
642 before DESIRED_ROW is made current. The window being updated is
643 found in updated_window. This function It is called from
644 update_window_line only if it is known that there are differences
645 between bitmaps to be drawn between current row and DESIRED_ROW. */
648 x_after_update_window_line (desired_row
)
649 struct glyph_row
*desired_row
;
651 struct window
*w
= updated_window
;
657 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
658 desired_row
->redraw_fringe_bitmaps_p
= 1;
660 /* When a window has disappeared, make sure that no rest of
661 full-width rows stays visible in the internal border. Could
662 check here if updated_window is the leftmost/rightmost window,
663 but I guess it's not worth doing since vertically split windows
664 are almost never used, internal border is rarely set, and the
665 overhead is very small. */
666 if (windows_or_buffers_changed
667 && desired_row
->full_width_p
668 && (f
= XFRAME (w
->frame
),
669 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
671 && (height
= desired_row
->visible_height
,
674 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
676 /* Internal border is drawn below the tool bar. */
677 if (WINDOWP (f
->tool_bar_window
)
678 && w
== XWINDOW (f
->tool_bar_window
))
682 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
683 0, y
, width
, height
, False
);
684 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
685 FRAME_PIXEL_WIDTH (f
) - width
,
686 y
, width
, height
, False
);
692 x_draw_fringe_bitmap (w
, row
, p
)
694 struct glyph_row
*row
;
695 struct draw_fringe_bitmap_params
*p
;
697 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
698 Display
*display
= FRAME_X_DISPLAY (f
);
699 Window window
= FRAME_X_WINDOW (f
);
700 GC gc
= f
->output_data
.x
->normal_gc
;
701 struct face
*face
= p
->face
;
704 /* Must clip because of partially visible lines. */
705 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
708 /* Adjust position of "bottom aligned" bitmap on partially
711 int oldVH
= row
->visible_height
;
712 row
->visible_height
= p
->h
;
713 row
->y
-= rowY
- p
->y
;
714 x_clip_to_row (w
, row
, gc
);
716 row
->visible_height
= oldVH
;
719 x_clip_to_row (w
, row
, gc
);
721 if (p
->bx
>= 0 && !p
->overlay_p
)
723 /* In case the same realized face is used for fringes and
724 for something displayed in the text (e.g. face `region' on
725 mono-displays, the fill style may have been changed to
726 FillSolid in x_draw_glyph_string_background. */
728 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
730 XSetForeground (display
, face
->gc
, face
->background
);
732 XFillRectangle (display
, window
, face
->gc
,
733 p
->bx
, p
->by
, p
->nx
, p
->ny
);
736 XSetForeground (display
, face
->gc
, face
->foreground
);
742 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
743 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
747 bits
= (unsigned char *)(p
->bits
+ p
->dh
);
749 bits
= (unsigned char *)p
->bits
+ p
->dh
;
751 /* Draw the bitmap. I believe these small pixmaps can be cached
753 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
755 ? (p
->overlay_p
? face
->background
756 : f
->output_data
.x
->cursor_pixel
)
758 face
->background
, depth
);
762 clipmask
= XCreatePixmapFromBitmapData (display
,
763 FRAME_X_DISPLAY_INFO (f
)->root_window
,
766 gcv
.clip_mask
= clipmask
;
767 gcv
.clip_x_origin
= p
->x
;
768 gcv
.clip_y_origin
= p
->y
;
769 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
772 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
773 p
->wd
, p
->h
, p
->x
, p
->y
);
774 XFreePixmap (display
, pixmap
);
778 gcv
.clip_mask
= (Pixmap
) 0;
779 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
780 XFreePixmap (display
, clipmask
);
784 XSetClipMask (display
, gc
, None
);
789 /* This is called when starting Emacs and when restarting after
790 suspend. When starting Emacs, no X window is mapped. And nothing
791 must be done to Emacs's own window if it is suspended (though that
795 XTset_terminal_modes (struct display
*display
)
799 /* This is called when exiting or suspending Emacs. Exiting will make
800 the X-windows go away, and suspending requires no action. */
803 XTreset_terminal_modes (struct display
*display
)
809 /***********************************************************************
811 ***********************************************************************/
813 /* Function prototypes of this page. */
815 static int x_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
818 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
819 is not contained in the font. */
822 x_per_char_metric (font
, char2b
, font_type
)
825 int font_type
; /* unused on X */
827 /* The result metric information. */
828 XCharStruct
*pcm
= NULL
;
830 xassert (font
&& char2b
);
832 if (font
->per_char
!= NULL
)
834 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
836 /* min_char_or_byte2 specifies the linear character index
837 corresponding to the first element of the per_char array,
838 max_char_or_byte2 is the index of the last character. A
839 character with non-zero CHAR2B->byte1 is not in the font.
840 A character with byte2 less than min_char_or_byte2 or
841 greater max_char_or_byte2 is not in the font. */
842 if (char2b
->byte1
== 0
843 && char2b
->byte2
>= font
->min_char_or_byte2
844 && char2b
->byte2
<= font
->max_char_or_byte2
)
845 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
849 /* If either min_byte1 or max_byte1 are nonzero, both
850 min_char_or_byte2 and max_char_or_byte2 are less than
851 256, and the 2-byte character index values corresponding
852 to the per_char array element N (counting from 0) are:
854 byte1 = N/D + min_byte1
855 byte2 = N\D + min_char_or_byte2
859 D = max_char_or_byte2 - min_char_or_byte2 + 1
861 \ = integer modulus */
862 if (char2b
->byte1
>= font
->min_byte1
863 && char2b
->byte1
<= font
->max_byte1
864 && char2b
->byte2
>= font
->min_char_or_byte2
865 && char2b
->byte2
<= font
->max_char_or_byte2
)
867 pcm
= (font
->per_char
868 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
869 * (char2b
->byte1
- font
->min_byte1
))
870 + (char2b
->byte2
- font
->min_char_or_byte2
));
876 /* If the per_char pointer is null, all glyphs between the first
877 and last character indexes inclusive have the same
878 information, as given by both min_bounds and max_bounds. */
879 if (char2b
->byte2
>= font
->min_char_or_byte2
880 && char2b
->byte2
<= font
->max_char_or_byte2
)
881 pcm
= &font
->max_bounds
;
885 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
890 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
891 the two-byte form of C. Encoding is returned in *CHAR2B. */
894 x_encode_char (c
, char2b
, font_info
, two_byte_p
)
897 struct font_info
*font_info
;
900 int charset
= CHAR_CHARSET (c
);
901 XFontStruct
*font
= font_info
->font
;
903 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
904 This may be either a program in a special encoder language or a
906 if (font_info
->font_encoder
)
908 /* It's a program. */
909 struct ccl_program
*ccl
= font_info
->font_encoder
;
911 if (CHARSET_DIMENSION (charset
) == 1)
913 ccl
->reg
[0] = charset
;
914 ccl
->reg
[1] = char2b
->byte2
;
919 ccl
->reg
[0] = charset
;
920 ccl
->reg
[1] = char2b
->byte1
;
921 ccl
->reg
[2] = char2b
->byte2
;
924 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
926 /* We assume that MSBs are appropriately set/reset by CCL
928 if (font
->max_byte1
== 0) /* 1-byte font */
929 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
931 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
933 else if (font_info
->encoding
[charset
])
935 /* Fixed encoding scheme. See fontset.h for the meaning of the
937 int enc
= font_info
->encoding
[charset
];
939 if ((enc
== 1 || enc
== 2)
940 && CHARSET_DIMENSION (charset
) == 2)
941 char2b
->byte1
|= 0x80;
943 if (enc
== 1 || enc
== 3)
944 char2b
->byte2
|= 0x80;
948 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
950 return FONT_TYPE_UNKNOWN
;
955 /***********************************************************************
957 ***********************************************************************/
961 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
962 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
963 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
965 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
966 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
967 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
968 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
969 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
970 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
971 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
972 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
973 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
974 unsigned long *, double, int));
975 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
976 double, int, unsigned long));
977 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
978 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
979 static void x_draw_image_relief
P_ ((struct glyph_string
*));
980 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
981 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
982 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
984 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
985 int, int, int, int, int, int,
987 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
988 int, int, int, XRectangle
*));
991 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
995 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1000 struct glyph_string
*s
;
1002 if (s
->font
== FRAME_FONT (s
->f
)
1003 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1004 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1006 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
1009 /* Cursor on non-default face: must merge. */
1013 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
1014 xgcv
.foreground
= s
->face
->background
;
1016 /* If the glyph would be invisible, try a different foreground. */
1017 if (xgcv
.foreground
== xgcv
.background
)
1018 xgcv
.foreground
= s
->face
->foreground
;
1019 if (xgcv
.foreground
== xgcv
.background
)
1020 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
1021 if (xgcv
.foreground
== xgcv
.background
)
1022 xgcv
.foreground
= s
->face
->foreground
;
1024 /* Make sure the cursor is distinct from text in this face. */
1025 if (xgcv
.background
== s
->face
->background
1026 && xgcv
.foreground
== s
->face
->foreground
)
1028 xgcv
.background
= s
->face
->foreground
;
1029 xgcv
.foreground
= s
->face
->background
;
1032 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1033 xgcv
.font
= s
->font
->fid
;
1034 xgcv
.graphics_exposures
= False
;
1035 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1037 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1038 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1041 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1042 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1044 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1049 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1052 x_set_mouse_face_gc (s
)
1053 struct glyph_string
*s
;
1058 /* What face has to be used last for the mouse face? */
1059 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1060 face
= FACE_FROM_ID (s
->f
, face_id
);
1062 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1064 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1065 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1067 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1068 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1069 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1071 /* If font in this face is same as S->font, use it. */
1072 if (s
->font
== s
->face
->font
)
1073 s
->gc
= s
->face
->gc
;
1076 /* Otherwise construct scratch_cursor_gc with values from FACE
1081 xgcv
.background
= s
->face
->background
;
1082 xgcv
.foreground
= s
->face
->foreground
;
1083 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1084 xgcv
.font
= s
->font
->fid
;
1085 xgcv
.graphics_exposures
= False
;
1086 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
1088 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1089 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1092 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1093 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1095 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1098 xassert (s
->gc
!= 0);
1102 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1103 Faces to use in the mode line have already been computed when the
1104 matrix was built, so there isn't much to do, here. */
1107 x_set_mode_line_face_gc (s
)
1108 struct glyph_string
*s
;
1110 s
->gc
= s
->face
->gc
;
1114 /* Set S->gc of glyph string S for drawing that glyph string. Set
1115 S->stippled_p to a non-zero value if the face of S has a stipple
1119 x_set_glyph_string_gc (s
)
1120 struct glyph_string
*s
;
1122 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1124 if (s
->hl
== DRAW_NORMAL_TEXT
)
1126 s
->gc
= s
->face
->gc
;
1127 s
->stippled_p
= s
->face
->stipple
!= 0;
1129 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1131 x_set_mode_line_face_gc (s
);
1132 s
->stippled_p
= s
->face
->stipple
!= 0;
1134 else if (s
->hl
== DRAW_CURSOR
)
1136 x_set_cursor_gc (s
);
1139 else if (s
->hl
== DRAW_MOUSE_FACE
)
1141 x_set_mouse_face_gc (s
);
1142 s
->stippled_p
= s
->face
->stipple
!= 0;
1144 else if (s
->hl
== DRAW_IMAGE_RAISED
1145 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1147 s
->gc
= s
->face
->gc
;
1148 s
->stippled_p
= s
->face
->stipple
!= 0;
1152 s
->gc
= s
->face
->gc
;
1153 s
->stippled_p
= s
->face
->stipple
!= 0;
1156 /* GC must have been set. */
1157 xassert (s
->gc
!= 0);
1161 /* Set clipping for output of glyph string S. S may be part of a mode
1162 line or menu if we don't have X toolkit support. */
1165 x_set_glyph_string_clipping (s
)
1166 struct glyph_string
*s
;
1169 get_glyph_string_clip_rect (s
, &r
);
1170 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
1175 Compute left and right overhang of glyph string S. If S is a glyph
1176 string for a composition, assume overhangs don't exist. */
1179 x_compute_glyph_string_overhangs (s
)
1180 struct glyph_string
*s
;
1183 && s
->first_glyph
->type
== CHAR_GLYPH
)
1186 int direction
, font_ascent
, font_descent
;
1187 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1188 &font_ascent
, &font_descent
, &cs
);
1189 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1190 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1195 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1198 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1199 struct glyph_string
*s
;
1203 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1204 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1205 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1206 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1210 /* Draw the background of glyph_string S. If S->background_filled_p
1211 is non-zero don't draw it. FORCE_P non-zero means draw the
1212 background even if it wouldn't be drawn normally. This is used
1213 when a string preceding S draws into the background of S, or S
1214 contains the first component of a composition. */
1217 x_draw_glyph_string_background (s
, force_p
)
1218 struct glyph_string
*s
;
1221 /* Nothing to do if background has already been drawn or if it
1222 shouldn't be drawn in the first place. */
1223 if (!s
->background_filled_p
)
1225 int box_line_width
= max (s
->face
->box_line_width
, 0);
1229 /* Fill background with a stipple pattern. */
1230 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1231 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1232 s
->y
+ box_line_width
,
1233 s
->background_width
,
1234 s
->height
- 2 * box_line_width
);
1235 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1236 s
->background_filled_p
= 1;
1238 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1239 || s
->font_not_found_p
1240 || s
->extends_to_end_of_line_p
1243 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1244 s
->background_width
,
1245 s
->height
- 2 * box_line_width
);
1246 s
->background_filled_p
= 1;
1252 /* Draw the foreground of glyph string S. */
1255 x_draw_glyph_string_foreground (s
)
1256 struct glyph_string
*s
;
1260 /* If first glyph of S has a left box line, start drawing the text
1261 of S to the right of that box line. */
1262 if (s
->face
->box
!= FACE_NO_BOX
1263 && s
->first_glyph
->left_box_line_p
)
1264 x
= s
->x
+ abs (s
->face
->box_line_width
);
1268 /* Draw characters of S as rectangles if S's font could not be
1270 if (s
->font_not_found_p
)
1272 for (i
= 0; i
< s
->nchars
; ++i
)
1274 struct glyph
*g
= s
->first_glyph
+ i
;
1275 XDrawRectangle (s
->display
, s
->window
,
1276 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1278 x
+= g
->pixel_width
;
1283 char *char1b
= (char *) s
->char2b
;
1284 int boff
= s
->font_info
->baseline_offset
;
1286 if (s
->font_info
->vertical_centering
)
1287 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1289 /* If we can use 8-bit functions, condense S->char2b. */
1291 for (i
= 0; i
< s
->nchars
; ++i
)
1292 char1b
[i
] = s
->char2b
[i
].byte2
;
1294 /* Draw text with XDrawString if background has already been
1295 filled. Otherwise, use XDrawImageString. (Note that
1296 XDrawImageString is usually faster than XDrawString.) Always
1297 use XDrawImageString when drawing the cursor so that there is
1298 no chance that characters under a box cursor are invisible. */
1299 if (s
->for_overlaps_p
1300 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1302 /* Draw characters with 16-bit or 8-bit functions. */
1304 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
1305 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1307 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
1308 s
->ybase
- boff
, char1b
, s
->nchars
);
1313 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
1314 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1316 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
1317 s
->ybase
- boff
, char1b
, s
->nchars
);
1320 if (s
->face
->overstrike
)
1322 /* For overstriking (to simulate bold-face), draw the
1323 characters again shifted to the right by one pixel. */
1325 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
+ 1,
1326 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1328 XDrawString (s
->display
, s
->window
, s
->gc
, x
+ 1,
1329 s
->ybase
- boff
, char1b
, s
->nchars
);
1334 /* Draw the foreground of composite glyph string S. */
1337 x_draw_composite_glyph_string_foreground (s
)
1338 struct glyph_string
*s
;
1342 /* If first glyph of S has a left box line, start drawing the text
1343 of S to the right of that box line. */
1344 if (s
->face
->box
!= FACE_NO_BOX
1345 && s
->first_glyph
->left_box_line_p
)
1346 x
= s
->x
+ abs (s
->face
->box_line_width
);
1350 /* S is a glyph string for a composition. S->gidx is the index of
1351 the first character drawn for glyphs of this composition.
1352 S->gidx == 0 means we are drawing the very first character of
1353 this composition. */
1355 /* Draw a rectangle for the composition if the font for the very
1356 first character of the composition could not be loaded. */
1357 if (s
->font_not_found_p
)
1360 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1361 s
->width
- 1, s
->height
- 1);
1365 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1367 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1368 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1369 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1371 if (s
->face
->overstrike
)
1372 XDrawString16 (s
->display
, s
->window
, s
->gc
,
1373 x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1374 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1381 #ifdef USE_X_TOOLKIT
1383 static struct frame
*x_frame_of_widget
P_ ((Widget
));
1384 static Boolean cvt_string_to_pixel
P_ ((Display
*, XrmValue
*, Cardinal
*,
1385 XrmValue
*, XrmValue
*, XtPointer
*));
1386 static void cvt_pixel_dtor
P_ ((XtAppContext
, XrmValue
*, XtPointer
,
1387 XrmValue
*, Cardinal
*));
1390 /* Return the frame on which widget WIDGET is used.. Abort if frame
1391 cannot be determined. */
1393 static struct frame
*
1394 x_frame_of_widget (widget
)
1397 struct x_display_info
*dpyinfo
;
1401 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1403 /* Find the top-level shell of the widget. Note that this function
1404 can be called when the widget is not yet realized, so XtWindow
1405 (widget) == 0. That's the reason we can't simply use
1406 x_any_window_to_frame. */
1407 while (!XtIsTopLevelShell (widget
))
1408 widget
= XtParent (widget
);
1410 /* Look for a frame with that top-level widget. Allocate the color
1411 on that frame to get the right gamma correction value. */
1412 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
1413 if (GC_FRAMEP (XCAR (tail
))
1414 && (f
= XFRAME (XCAR (tail
)),
1416 && f
->output_data
.nothing
!= 1
1417 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1418 && f
->output_data
.x
->widget
== widget
)
1425 /* Allocate the color COLOR->pixel on the screen and display of
1426 widget WIDGET in colormap CMAP. If an exact match cannot be
1427 allocated, try the nearest color available. Value is non-zero
1428 if successful. This is called from lwlib. */
1431 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
1436 struct frame
*f
= x_frame_of_widget (widget
);
1437 return x_alloc_nearest_color (f
, cmap
, color
);
1441 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1442 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1443 If this produces the same color as PIXEL, try a color where all RGB
1444 values have DELTA added. Return the allocated color in *PIXEL.
1445 DISPLAY is the X display, CMAP is the colormap to operate on.
1446 Value is non-zero if successful. */
1449 x_alloc_lighter_color_for_widget (widget
, display
, cmap
, pixel
, factor
, delta
)
1453 unsigned long *pixel
;
1457 struct frame
*f
= x_frame_of_widget (widget
);
1458 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1462 /* Structure specifying which arguments should be passed by Xt to
1463 cvt_string_to_pixel. We want the widget's screen and colormap. */
1465 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1467 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1469 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1474 /* The address of this variable is returned by
1475 cvt_string_to_pixel. */
1477 static Pixel cvt_string_to_pixel_value
;
1480 /* Convert a color name to a pixel color.
1482 DPY is the display we are working on.
1484 ARGS is an array of *NARGS XrmValue structures holding additional
1485 information about the widget for which the conversion takes place.
1486 The contents of this array are determined by the specification
1487 in cvt_string_to_pixel_args.
1489 FROM is a pointer to an XrmValue which points to the color name to
1490 convert. TO is an XrmValue in which to return the pixel color.
1492 CLOSURE_RET is a pointer to user-data, in which we record if
1493 we allocated the color or not.
1495 Value is True if successful, False otherwise. */
1498 cvt_string_to_pixel (dpy
, args
, nargs
, from
, to
, closure_ret
)
1502 XrmValue
*from
, *to
;
1503 XtPointer
*closure_ret
;
1513 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1514 "wrongParameters", "cvt_string_to_pixel",
1516 "Screen and colormap args required", NULL
, NULL
);
1520 screen
= *(Screen
**) args
[0].addr
;
1521 cmap
= *(Colormap
*) args
[1].addr
;
1522 color_name
= (String
) from
->addr
;
1524 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1526 *closure_ret
= (XtPointer
) False
;
1527 pixel
= WhitePixelOfScreen (screen
);
1529 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1531 *closure_ret
= (XtPointer
) False
;
1532 pixel
= BlackPixelOfScreen (screen
);
1534 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1535 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1537 pixel
= color
.pixel
;
1538 *closure_ret
= (XtPointer
) True
;
1543 Cardinal nparams
= 1;
1545 params
[0] = color_name
;
1546 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1547 "badValue", "cvt_string_to_pixel",
1548 "XtToolkitError", "Invalid color `%s'",
1553 if (to
->addr
!= NULL
)
1555 if (to
->size
< sizeof (Pixel
))
1557 to
->size
= sizeof (Pixel
);
1561 *(Pixel
*) to
->addr
= pixel
;
1565 cvt_string_to_pixel_value
= pixel
;
1566 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1569 to
->size
= sizeof (Pixel
);
1574 /* Free a pixel color which was previously allocated via
1575 cvt_string_to_pixel. This is registered as the destructor
1576 for this type of resource via XtSetTypeConverter.
1578 APP is the application context in which we work.
1580 TO is a pointer to an XrmValue holding the color to free.
1581 CLOSURE is the value we stored in CLOSURE_RET for this color
1582 in cvt_string_to_pixel.
1584 ARGS and NARGS are like for cvt_string_to_pixel. */
1587 cvt_pixel_dtor (app
, to
, closure
, args
, nargs
)
1596 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1598 "Screen and colormap arguments required",
1601 else if (closure
!= NULL
)
1603 /* We did allocate the pixel, so free it. */
1604 Screen
*screen
= *(Screen
**) args
[0].addr
;
1605 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1606 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1607 (Pixel
*) to
->addr
, 1);
1612 #endif /* USE_X_TOOLKIT */
1615 /* Value is an array of XColor structures for the contents of the
1616 color map of display DPY. Set *NCELLS to the size of the array.
1617 Note that this probably shouldn't be called for large color maps,
1618 say a 24-bit TrueColor map. */
1620 static const XColor
*
1621 x_color_cells (dpy
, ncells
)
1625 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1627 if (dpyinfo
->color_cells
== NULL
)
1629 Screen
*screen
= dpyinfo
->screen
;
1632 dpyinfo
->ncolor_cells
1633 = XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1634 dpyinfo
->color_cells
1635 = (XColor
*) xmalloc (dpyinfo
->ncolor_cells
1636 * sizeof *dpyinfo
->color_cells
);
1638 for (i
= 0; i
< dpyinfo
->ncolor_cells
; ++i
)
1639 dpyinfo
->color_cells
[i
].pixel
= i
;
1641 XQueryColors (dpy
, dpyinfo
->cmap
,
1642 dpyinfo
->color_cells
, dpyinfo
->ncolor_cells
);
1645 *ncells
= dpyinfo
->ncolor_cells
;
1646 return dpyinfo
->color_cells
;
1650 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1651 colors in COLORS. Use cached information, if available. */
1654 x_query_colors (f
, colors
, ncolors
)
1659 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1661 if (dpyinfo
->color_cells
)
1664 for (i
= 0; i
< ncolors
; ++i
)
1666 unsigned long pixel
= colors
[i
].pixel
;
1667 xassert (pixel
< dpyinfo
->ncolor_cells
);
1668 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1669 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1673 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1677 /* On frame F, translate pixel color to RGB values for the color in
1678 COLOR. Use cached information, if available. */
1681 x_query_color (f
, color
)
1685 x_query_colors (f
, color
, 1);
1689 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1690 exact match can't be allocated, try the nearest color available.
1691 Value is non-zero if successful. Set *COLOR to the color
1695 x_alloc_nearest_color_1 (dpy
, cmap
, color
)
1702 rc
= XAllocColor (dpy
, cmap
, color
);
1705 /* If we got to this point, the colormap is full, so we're going
1706 to try to get the next closest color. The algorithm used is
1707 a least-squares matching, which is what X uses for closest
1708 color matching with StaticColor visuals. */
1710 unsigned long nearest_delta
= ~0;
1712 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1714 for (nearest
= i
= 0; i
< ncells
; ++i
)
1716 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1717 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1718 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1719 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1721 if (delta
< nearest_delta
)
1724 nearest_delta
= delta
;
1728 color
->red
= cells
[nearest
].red
;
1729 color
->green
= cells
[nearest
].green
;
1730 color
->blue
= cells
[nearest
].blue
;
1731 rc
= XAllocColor (dpy
, cmap
, color
);
1735 /* If allocation succeeded, and the allocated pixel color is not
1736 equal to a cached pixel color recorded earlier, there was a
1737 change in the colormap, so clear the color cache. */
1738 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1739 XColor
*cached_color
;
1741 if (dpyinfo
->color_cells
1742 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1743 (cached_color
->red
!= color
->red
1744 || cached_color
->blue
!= color
->blue
1745 || cached_color
->green
!= color
->green
)))
1747 xfree (dpyinfo
->color_cells
);
1748 dpyinfo
->color_cells
= NULL
;
1749 dpyinfo
->ncolor_cells
= 0;
1753 #ifdef DEBUG_X_COLORS
1755 register_color (color
->pixel
);
1756 #endif /* DEBUG_X_COLORS */
1762 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1763 exact match can't be allocated, try the nearest color available.
1764 Value is non-zero if successful. Set *COLOR to the color
1768 x_alloc_nearest_color (f
, cmap
, color
)
1773 gamma_correct (f
, color
);
1774 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1778 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1779 It's necessary to do this instead of just using PIXEL directly to
1780 get color reference counts right. */
1783 x_copy_color (f
, pixel
)
1785 unsigned long pixel
;
1789 color
.pixel
= pixel
;
1791 x_query_color (f
, &color
);
1792 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1794 #ifdef DEBUG_X_COLORS
1795 register_color (pixel
);
1801 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
1802 It's necessary to do this instead of just using PIXEL directly to
1803 get color reference counts right. */
1806 x_copy_dpy_color (dpy
, cmap
, pixel
)
1809 unsigned long pixel
;
1813 color
.pixel
= pixel
;
1815 XQueryColor (dpy
, cmap
, &color
);
1816 XAllocColor (dpy
, cmap
, &color
);
1818 #ifdef DEBUG_X_COLORS
1819 register_color (pixel
);
1825 /* Brightness beyond which a color won't have its highlight brightness
1828 Nominally, highlight colors for `3d' faces are calculated by
1829 brightening an object's color by a constant scale factor, but this
1830 doesn't yield good results for dark colors, so for colors who's
1831 brightness is less than this value (on a scale of 0-65535) have an
1832 use an additional additive factor.
1834 The value here is set so that the default menu-bar/mode-line color
1835 (grey75) will not have its highlights changed at all. */
1836 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1839 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1840 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1841 If this produces the same color as PIXEL, try a color where all RGB
1842 values have DELTA added. Return the allocated color in *PIXEL.
1843 DISPLAY is the X display, CMAP is the colormap to operate on.
1844 Value is non-zero if successful. */
1847 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
1851 unsigned long *pixel
;
1859 /* Get RGB color values. */
1860 color
.pixel
= *pixel
;
1861 x_query_color (f
, &color
);
1863 /* Change RGB values by specified FACTOR. Avoid overflow! */
1864 xassert (factor
>= 0);
1865 new.red
= min (0xffff, factor
* color
.red
);
1866 new.green
= min (0xffff, factor
* color
.green
);
1867 new.blue
= min (0xffff, factor
* color
.blue
);
1869 /* Calculate brightness of COLOR. */
1870 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
1872 /* We only boost colors that are darker than
1873 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1874 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1875 /* Make an additive adjustment to NEW, because it's dark enough so
1876 that scaling by FACTOR alone isn't enough. */
1878 /* How far below the limit this color is (0 - 1, 1 being darker). */
1879 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1880 /* The additive adjustment. */
1881 int min_delta
= delta
* dimness
* factor
/ 2;
1885 new.red
= max (0, new.red
- min_delta
);
1886 new.green
= max (0, new.green
- min_delta
);
1887 new.blue
= max (0, new.blue
- min_delta
);
1891 new.red
= min (0xffff, min_delta
+ new.red
);
1892 new.green
= min (0xffff, min_delta
+ new.green
);
1893 new.blue
= min (0xffff, min_delta
+ new.blue
);
1897 /* Try to allocate the color. */
1898 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1901 if (new.pixel
== *pixel
)
1903 /* If we end up with the same color as before, try adding
1904 delta to the RGB values. */
1905 x_free_colors (f
, &new.pixel
, 1);
1907 new.red
= min (0xffff, delta
+ color
.red
);
1908 new.green
= min (0xffff, delta
+ color
.green
);
1909 new.blue
= min (0xffff, delta
+ color
.blue
);
1910 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1921 /* Set up the foreground color for drawing relief lines of glyph
1922 string S. RELIEF is a pointer to a struct relief containing the GC
1923 with which lines will be drawn. Use a color that is FACTOR or
1924 DELTA lighter or darker than the relief's background which is found
1925 in S->f->output_data.x->relief_background. If such a color cannot
1926 be allocated, use DEFAULT_PIXEL, instead. */
1929 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1931 struct relief
*relief
;
1934 unsigned long default_pixel
;
1937 struct x_output
*di
= f
->output_data
.x
;
1938 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
1939 unsigned long pixel
;
1940 unsigned long background
= di
->relief_background
;
1941 Colormap cmap
= FRAME_X_COLORMAP (f
);
1942 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1943 Display
*dpy
= FRAME_X_DISPLAY (f
);
1945 xgcv
.graphics_exposures
= False
;
1946 xgcv
.line_width
= 1;
1948 /* Free previously allocated color. The color cell will be reused
1949 when it has been freed as many times as it was allocated, so this
1950 doesn't affect faces using the same colors. */
1952 && relief
->allocated_p
)
1954 x_free_colors (f
, &relief
->pixel
, 1);
1955 relief
->allocated_p
= 0;
1958 /* Allocate new color. */
1959 xgcv
.foreground
= default_pixel
;
1961 if (dpyinfo
->n_planes
!= 1
1962 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
1964 relief
->allocated_p
= 1;
1965 xgcv
.foreground
= relief
->pixel
= pixel
;
1968 if (relief
->gc
== 0)
1970 xgcv
.stipple
= dpyinfo
->gray
;
1972 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
1975 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
1979 /* Set up colors for the relief lines around glyph string S. */
1982 x_setup_relief_colors (s
)
1983 struct glyph_string
*s
;
1985 struct x_output
*di
= s
->f
->output_data
.x
;
1986 unsigned long color
;
1988 if (s
->face
->use_box_color_for_shadows_p
)
1989 color
= s
->face
->box_color
;
1990 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1992 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1993 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1998 /* Get the background color of the face. */
1999 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2000 color
= xgcv
.background
;
2003 if (di
->white_relief
.gc
== 0
2004 || color
!= di
->relief_background
)
2006 di
->relief_background
= color
;
2007 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2008 WHITE_PIX_DEFAULT (s
->f
));
2009 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2010 BLACK_PIX_DEFAULT (s
->f
));
2015 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2016 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2017 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2018 relief. LEFT_P non-zero means draw a relief on the left side of
2019 the rectangle. RIGHT_P non-zero means draw a relief on the right
2020 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2024 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2025 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2027 int left_x
, top_y
, right_x
, bottom_y
, width
;
2028 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2029 XRectangle
*clip_rect
;
2031 Display
*dpy
= FRAME_X_DISPLAY (f
);
2032 Window window
= FRAME_X_WINDOW (f
);
2037 gc
= f
->output_data
.x
->white_relief
.gc
;
2039 gc
= f
->output_data
.x
->black_relief
.gc
;
2040 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2044 for (i
= 0; i
< width
; ++i
)
2045 XDrawLine (dpy
, window
, gc
,
2046 left_x
+ i
* left_p
, top_y
+ i
,
2047 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2051 for (i
= 0; i
< width
; ++i
)
2052 XDrawLine (dpy
, window
, gc
,
2053 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2055 XSetClipMask (dpy
, gc
, None
);
2057 gc
= f
->output_data
.x
->black_relief
.gc
;
2059 gc
= f
->output_data
.x
->white_relief
.gc
;
2060 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2064 for (i
= 0; i
< width
; ++i
)
2065 XDrawLine (dpy
, window
, gc
,
2066 left_x
+ i
* left_p
, bottom_y
- i
,
2067 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2071 for (i
= 0; i
< width
; ++i
)
2072 XDrawLine (dpy
, window
, gc
,
2073 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2075 XSetClipMask (dpy
, gc
, None
);
2079 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2080 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2081 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2082 left side of the rectangle. RIGHT_P non-zero means draw a line
2083 on the right side of the rectangle. CLIP_RECT is the clipping
2084 rectangle to use when drawing. */
2087 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2088 left_p
, right_p
, clip_rect
)
2089 struct glyph_string
*s
;
2090 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2091 XRectangle
*clip_rect
;
2095 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2096 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2097 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2100 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2101 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2105 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2106 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2109 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2110 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2114 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2115 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2117 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2118 XSetClipMask (s
->display
, s
->gc
, None
);
2122 /* Draw a box around glyph string S. */
2125 x_draw_glyph_string_box (s
)
2126 struct glyph_string
*s
;
2128 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2129 int left_p
, right_p
;
2130 struct glyph
*last_glyph
;
2131 XRectangle clip_rect
;
2133 last_x
= window_box_right (s
->w
, s
->area
);
2134 if (s
->row
->full_width_p
2135 && !s
->w
->pseudo_window_p
)
2137 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2138 if (s
->area
!= RIGHT_MARGIN_AREA
2139 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2140 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2143 /* The glyph that may have a right box line. */
2144 last_glyph
= (s
->cmp
|| s
->img
2146 : s
->first_glyph
+ s
->nchars
- 1);
2148 width
= abs (s
->face
->box_line_width
);
2149 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2151 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2153 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2155 bottom_y
= top_y
+ s
->height
- 1;
2157 left_p
= (s
->first_glyph
->left_box_line_p
2158 || (s
->hl
== DRAW_MOUSE_FACE
2160 || s
->prev
->hl
!= s
->hl
)));
2161 right_p
= (last_glyph
->right_box_line_p
2162 || (s
->hl
== DRAW_MOUSE_FACE
2164 || s
->next
->hl
!= s
->hl
)));
2166 get_glyph_string_clip_rect (s
, &clip_rect
);
2168 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2169 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2170 left_p
, right_p
, &clip_rect
);
2173 x_setup_relief_colors (s
);
2174 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2175 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2180 /* Draw foreground of image glyph string S. */
2183 x_draw_image_foreground (s
)
2184 struct glyph_string
*s
;
2187 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2189 /* If first glyph of S has a left box line, start drawing it to the
2190 right of that line. */
2191 if (s
->face
->box
!= FACE_NO_BOX
2192 && s
->first_glyph
->left_box_line_p
2194 x
+= abs (s
->face
->box_line_width
);
2196 /* If there is a margin around the image, adjust x- and y-position
2198 if (s
->slice
.x
== 0)
2199 x
+= s
->img
->hmargin
;
2200 if (s
->slice
.y
== 0)
2201 y
+= s
->img
->vmargin
;
2207 /* We can't set both a clip mask and use XSetClipRectangles
2208 because the latter also sets a clip mask. We also can't
2209 trust on the shape extension to be available
2210 (XShapeCombineRegion). So, compute the rectangle to draw
2212 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2215 XRectangle clip_rect
, image_rect
, r
;
2217 xgcv
.clip_mask
= s
->img
->mask
;
2218 xgcv
.clip_x_origin
= x
;
2219 xgcv
.clip_y_origin
= y
;
2220 xgcv
.function
= GXcopy
;
2221 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2223 get_glyph_string_clip_rect (s
, &clip_rect
);
2226 image_rect
.width
= s
->slice
.width
;
2227 image_rect
.height
= s
->slice
.height
;
2228 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2229 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2230 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2231 r
.width
, r
.height
, r
.x
, r
.y
);
2235 XRectangle clip_rect
, image_rect
, r
;
2237 get_glyph_string_clip_rect (s
, &clip_rect
);
2240 image_rect
.width
= s
->slice
.width
;
2241 image_rect
.height
= s
->slice
.height
;
2242 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2243 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2244 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2245 r
.width
, r
.height
, r
.x
, r
.y
);
2247 /* When the image has a mask, we can expect that at
2248 least part of a mouse highlight or a block cursor will
2249 be visible. If the image doesn't have a mask, make
2250 a block cursor visible by drawing a rectangle around
2251 the image. I believe it's looking better if we do
2252 nothing here for mouse-face. */
2253 if (s
->hl
== DRAW_CURSOR
)
2255 int r
= s
->img
->relief
;
2257 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
2259 s
->slice
.width
+ r
*2 - 1,
2260 s
->slice
.height
+ r
*2 - 1);
2265 /* Draw a rectangle if image could not be loaded. */
2266 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2267 s
->slice
.width
- 1, s
->slice
.height
- 1);
2271 /* Draw a relief around the image glyph string S. */
2274 x_draw_image_relief (s
)
2275 struct glyph_string
*s
;
2277 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2280 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2282 /* If first glyph of S has a left box line, start drawing it to the
2283 right of that line. */
2284 if (s
->face
->box
!= FACE_NO_BOX
2285 && s
->first_glyph
->left_box_line_p
2287 x
+= abs (s
->face
->box_line_width
);
2289 /* If there is a margin around the image, adjust x- and y-position
2291 if (s
->slice
.x
== 0)
2292 x
+= s
->img
->hmargin
;
2293 if (s
->slice
.y
== 0)
2294 y
+= s
->img
->vmargin
;
2296 if (s
->hl
== DRAW_IMAGE_SUNKEN
2297 || s
->hl
== DRAW_IMAGE_RAISED
)
2299 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2300 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2304 thick
= abs (s
->img
->relief
);
2305 raised_p
= s
->img
->relief
> 0;
2310 x1
= x
+ s
->slice
.width
+ thick
- 1;
2311 y1
= y
+ s
->slice
.height
+ thick
- 1;
2313 x_setup_relief_colors (s
);
2314 get_glyph_string_clip_rect (s
, &r
);
2315 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2317 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2319 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2324 /* Draw the foreground of image glyph string S to PIXMAP. */
2327 x_draw_image_foreground_1 (s
, pixmap
)
2328 struct glyph_string
*s
;
2332 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2334 /* If first glyph of S has a left box line, start drawing it to the
2335 right of that line. */
2336 if (s
->face
->box
!= FACE_NO_BOX
2337 && s
->first_glyph
->left_box_line_p
2339 x
+= abs (s
->face
->box_line_width
);
2341 /* If there is a margin around the image, adjust x- and y-position
2343 if (s
->slice
.x
== 0)
2344 x
+= s
->img
->hmargin
;
2345 if (s
->slice
.y
== 0)
2346 y
+= s
->img
->vmargin
;
2352 /* We can't set both a clip mask and use XSetClipRectangles
2353 because the latter also sets a clip mask. We also can't
2354 trust on the shape extension to be available
2355 (XShapeCombineRegion). So, compute the rectangle to draw
2357 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2361 xgcv
.clip_mask
= s
->img
->mask
;
2362 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
2363 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
2364 xgcv
.function
= GXcopy
;
2365 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2367 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2368 s
->slice
.x
, s
->slice
.y
,
2369 s
->slice
.width
, s
->slice
.height
, x
, y
);
2370 XSetClipMask (s
->display
, s
->gc
, None
);
2374 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2375 s
->slice
.x
, s
->slice
.y
,
2376 s
->slice
.width
, s
->slice
.height
, x
, y
);
2378 /* When the image has a mask, we can expect that at
2379 least part of a mouse highlight or a block cursor will
2380 be visible. If the image doesn't have a mask, make
2381 a block cursor visible by drawing a rectangle around
2382 the image. I believe it's looking better if we do
2383 nothing here for mouse-face. */
2384 if (s
->hl
== DRAW_CURSOR
)
2386 int r
= s
->img
->relief
;
2388 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2389 s
->slice
.width
+ r
*2 - 1,
2390 s
->slice
.height
+ r
*2 - 1);
2395 /* Draw a rectangle if image could not be loaded. */
2396 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2397 s
->slice
.width
- 1, s
->slice
.height
- 1);
2401 /* Draw part of the background of glyph string S. X, Y, W, and H
2402 give the rectangle to draw. */
2405 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2406 struct glyph_string
*s
;
2411 /* Fill background with a stipple pattern. */
2412 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2413 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2414 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2417 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2421 /* Draw image glyph string S.
2424 s->x +-------------------------
2427 | +-------------------------
2430 | | +-------------------
2436 x_draw_image_glyph_string (s
)
2437 struct glyph_string
*s
;
2439 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2440 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2442 Pixmap pixmap
= None
;
2445 if (s
->slice
.y
== 0)
2446 height
-= box_line_vwidth
;
2447 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
2448 height
-= box_line_vwidth
;
2450 /* Fill background with face under the image. Do it only if row is
2451 taller than image or if image has a clip mask to reduce
2453 s
->stippled_p
= s
->face
->stipple
!= 0;
2454 if (height
> s
->slice
.height
2458 || s
->img
->pixmap
== 0
2459 || s
->width
!= s
->background_width
)
2463 /* Create a pixmap as large as the glyph string. Fill it
2464 with the background color. Copy the image to it, using
2465 its mask. Copy the temporary pixmap to the display. */
2466 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2467 int depth
= DefaultDepthOfScreen (screen
);
2469 /* Create a pixmap as large as the glyph string. */
2470 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2471 s
->background_width
,
2474 /* Don't clip in the following because we're working on the
2476 XSetClipMask (s
->display
, s
->gc
, None
);
2478 /* Fill the pixmap with the background color/stipple. */
2481 /* Fill background with a stipple pattern. */
2482 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2483 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2484 0, 0, s
->background_width
, s
->height
);
2485 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2490 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2492 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2493 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2494 0, 0, s
->background_width
, s
->height
);
2495 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2503 if (s
->first_glyph
->left_box_line_p
2505 x
+= box_line_hwidth
;
2507 if (s
->slice
.y
== 0)
2508 y
+= box_line_vwidth
;
2510 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2513 s
->background_filled_p
= 1;
2516 /* Draw the foreground. */
2519 x_draw_image_foreground_1 (s
, pixmap
);
2520 x_set_glyph_string_clipping (s
);
2521 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2522 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2523 XFreePixmap (s
->display
, pixmap
);
2526 x_draw_image_foreground (s
);
2528 /* If we must draw a relief around the image, do it. */
2530 || s
->hl
== DRAW_IMAGE_RAISED
2531 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2532 x_draw_image_relief (s
);
2536 /* Draw stretch glyph string S. */
2539 x_draw_stretch_glyph_string (s
)
2540 struct glyph_string
*s
;
2542 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2543 s
->stippled_p
= s
->face
->stipple
!= 0;
2545 if (s
->hl
== DRAW_CURSOR
2546 && !x_stretch_cursor_p
)
2548 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2549 as wide as the stretch glyph. */
2550 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2553 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2555 /* Clear rest using the GC of the original non-cursor face. */
2556 if (width
< s
->background_width
)
2558 int x
= s
->x
+ width
, y
= s
->y
;
2559 int w
= s
->background_width
- width
, h
= s
->height
;
2563 if (s
->row
->mouse_face_p
2564 && cursor_in_mouse_face_p (s
->w
))
2566 x_set_mouse_face_gc (s
);
2572 get_glyph_string_clip_rect (s
, &r
);
2573 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2575 if (s
->face
->stipple
)
2577 /* Fill background with a stipple pattern. */
2578 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2579 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2580 XSetFillStyle (s
->display
, gc
, FillSolid
);
2585 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2586 XSetForeground (s
->display
, gc
, xgcv
.background
);
2587 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2588 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2592 else if (!s
->background_filled_p
)
2593 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2596 s
->background_filled_p
= 1;
2600 /* Draw glyph string S. */
2603 x_draw_glyph_string (s
)
2604 struct glyph_string
*s
;
2606 int relief_drawn_p
= 0;
2608 /* If S draws into the background of its successor, draw the
2609 background of the successor first so that S can draw into it.
2610 This makes S->next use XDrawString instead of XDrawImageString. */
2611 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2613 xassert (s
->next
->img
== NULL
);
2614 x_set_glyph_string_gc (s
->next
);
2615 x_set_glyph_string_clipping (s
->next
);
2616 x_draw_glyph_string_background (s
->next
, 1);
2619 /* Set up S->gc, set clipping and draw S. */
2620 x_set_glyph_string_gc (s
);
2622 /* Draw relief (if any) in advance for char/composition so that the
2623 glyph string can be drawn over it. */
2624 if (!s
->for_overlaps_p
2625 && s
->face
->box
!= FACE_NO_BOX
2626 && (s
->first_glyph
->type
== CHAR_GLYPH
2627 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2630 x_set_glyph_string_clipping (s
);
2631 x_draw_glyph_string_background (s
, 1);
2632 x_draw_glyph_string_box (s
);
2633 x_set_glyph_string_clipping (s
);
2637 x_set_glyph_string_clipping (s
);
2639 switch (s
->first_glyph
->type
)
2642 x_draw_image_glyph_string (s
);
2646 x_draw_stretch_glyph_string (s
);
2650 if (s
->for_overlaps_p
)
2651 s
->background_filled_p
= 1;
2653 x_draw_glyph_string_background (s
, 0);
2654 x_draw_glyph_string_foreground (s
);
2657 case COMPOSITE_GLYPH
:
2658 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2659 s
->background_filled_p
= 1;
2661 x_draw_glyph_string_background (s
, 1);
2662 x_draw_composite_glyph_string_foreground (s
);
2669 if (!s
->for_overlaps_p
)
2671 /* Draw underline. */
2672 if (s
->face
->underline_p
)
2674 unsigned long tem
, h
;
2677 /* Get the underline thickness. Default is 1 pixel. */
2678 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
2681 /* Get the underline position. This is the recommended
2682 vertical offset in pixels from the baseline to the top of
2683 the underline. This is a signed value according to the
2684 specs, and its default is
2686 ROUND ((maximum descent) / 2), with
2687 ROUND(x) = floor (x + 0.5) */
2689 if (x_use_underline_position_properties
2690 && XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &tem
))
2691 y
= s
->ybase
+ (long) tem
;
2692 else if (s
->face
->font
)
2693 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2695 y
= s
->y
+ s
->height
- h
;
2697 if (s
->face
->underline_defaulted_p
)
2698 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2699 s
->x
, y
, s
->width
, h
);
2703 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2704 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2705 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2706 s
->x
, y
, s
->width
, h
);
2707 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2711 /* Draw overline. */
2712 if (s
->face
->overline_p
)
2714 unsigned long dy
= 0, h
= 1;
2716 if (s
->face
->overline_color_defaulted_p
)
2717 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2722 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2723 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2724 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2726 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2730 /* Draw strike-through. */
2731 if (s
->face
->strike_through_p
)
2733 unsigned long h
= 1;
2734 unsigned long dy
= (s
->height
- h
) / 2;
2736 if (s
->face
->strike_through_color_defaulted_p
)
2737 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2742 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2743 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2744 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2746 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2750 /* Draw relief if not yet drawn. */
2751 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2752 x_draw_glyph_string_box (s
);
2755 /* Reset clipping. */
2756 XSetClipMask (s
->display
, s
->gc
, None
);
2759 /* Shift display to make room for inserted glyphs. */
2762 x_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2764 int x
, y
, width
, height
, shift_by
;
2766 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
2767 f
->output_data
.x
->normal_gc
,
2768 x
, y
, width
, height
,
2772 /* Delete N glyphs at the nominal cursor position. Not implemented
2776 x_delete_glyphs (f
, n
)
2784 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2785 If they are <= 0, this is probably an error. */
2788 x_clear_area (dpy
, window
, x
, y
, width
, height
, exposures
)
2795 xassert (width
> 0 && height
> 0);
2796 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
2800 /* Clear entire frame. If updating_frame is non-null, clear that
2801 frame. Otherwise clear the selected frame. */
2804 x_clear_frame (struct frame
*f
)
2806 /* Clearing the frame will erase any cursor, so mark them all as no
2808 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2809 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2810 output_cursor
.x
= -1;
2812 /* We don't set the output cursor here because there will always
2813 follow an explicit cursor_to. */
2815 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
2817 /* We have to clear the scroll bars, too. If we have changed
2818 colors or something like that, then they should be notified. */
2819 x_scroll_bar_clear (f
);
2821 XFlush (FRAME_X_DISPLAY (f
));
2824 xg_frame_cleared (f
);
2832 /* Invert the middle quarter of the frame for .15 sec. */
2834 /* We use the select system call to do the waiting, so we have to make
2835 sure it's available. If it isn't, we just won't do visual bells. */
2837 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
2840 /* Subtract the `struct timeval' values X and Y, storing the result in
2841 *RESULT. Return 1 if the difference is negative, otherwise 0. */
2844 timeval_subtract (result
, x
, y
)
2845 struct timeval
*result
, x
, y
;
2847 /* Perform the carry for the later subtraction by updating y. This
2848 is safer because on some systems the tv_sec member is unsigned. */
2849 if (x
.tv_usec
< y
.tv_usec
)
2851 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
2852 y
.tv_usec
-= 1000000 * nsec
;
2856 if (x
.tv_usec
- y
.tv_usec
> 1000000)
2858 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
2859 y
.tv_usec
+= 1000000 * nsec
;
2863 /* Compute the time remaining to wait. tv_usec is certainly
2865 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
2866 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
2868 /* Return indication of whether the result should be considered
2870 return x
.tv_sec
< y
.tv_sec
;
2882 /* Create a GC that will use the GXxor function to flip foreground
2883 pixels into background pixels. */
2887 values
.function
= GXxor
;
2888 values
.foreground
= (f
->output_data
.x
->foreground_pixel
2889 ^ f
->output_data
.x
->background_pixel
);
2891 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2892 GCFunction
| GCForeground
, &values
);
2896 /* Get the height not including a menu bar widget. */
2897 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
2898 /* Height of each line to flash. */
2899 int flash_height
= FRAME_LINE_HEIGHT (f
);
2900 /* These will be the left and right margins of the rectangles. */
2901 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
2902 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
2906 /* Don't flash the area between a scroll bar and the frame
2907 edge it is next to. */
2908 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
2910 case vertical_scroll_bar_left
:
2911 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2914 case vertical_scroll_bar_right
:
2915 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
2922 width
= flash_right
- flash_left
;
2924 /* If window is tall, flash top and bottom line. */
2925 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2927 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2929 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2930 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2931 width
, flash_height
);
2932 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2934 (height
- flash_height
2935 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2936 width
, flash_height
);
2939 /* If it is short, flash it all. */
2940 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2941 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2942 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2947 struct timeval wakeup
;
2949 EMACS_GET_TIME (wakeup
);
2951 /* Compute time to wait until, propagating carry from usecs. */
2952 wakeup
.tv_usec
+= 150000;
2953 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
2954 wakeup
.tv_usec
%= 1000000;
2956 /* Keep waiting until past the time wakeup or any input gets
2958 while (! detect_input_pending ())
2960 struct timeval current
;
2961 struct timeval timeout
;
2963 EMACS_GET_TIME (current
);
2965 /* Break if result would be negative. */
2966 if (timeval_subtract (¤t
, wakeup
, current
))
2969 /* How long `select' should wait. */
2971 timeout
.tv_usec
= 10000;
2973 /* Try to wait that long--but we might wake up sooner. */
2974 select (0, NULL
, NULL
, NULL
, &timeout
);
2978 /* If window is tall, flash top and bottom line. */
2979 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
2981 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2983 (FRAME_INTERNAL_BORDER_WIDTH (f
)
2984 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
2985 width
, flash_height
);
2986 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2988 (height
- flash_height
2989 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
2990 width
, flash_height
);
2993 /* If it is short, flash it all. */
2994 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
2995 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
2996 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
2998 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
3006 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3009 /* Make audible bell. */
3014 struct frame
*f
= SELECTED_FRAME ();
3016 if (FRAME_X_DISPLAY (f
))
3018 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3025 XBell (FRAME_X_DISPLAY (f
), 0);
3026 XFlush (FRAME_X_DISPLAY (f
));
3033 /* Specify how many text lines, from the top of the window,
3034 should be affected by insert-lines and delete-lines operations.
3035 This, and those operations, are used only within an update
3036 that is bounded by calls to x_update_begin and x_update_end. */
3039 XTset_terminal_window (n
)
3042 /* This function intentionally left blank. */
3047 /***********************************************************************
3049 ***********************************************************************/
3051 /* Perform an insert-lines or delete-lines operation, inserting N
3052 lines or deleting -N lines at vertical position VPOS. */
3055 x_ins_del_lines (f
, vpos
, n
)
3063 /* Scroll part of the display as described by RUN. */
3066 x_scroll_run (w
, run
)
3070 struct frame
*f
= XFRAME (w
->frame
);
3071 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3073 /* Get frame-relative bounding box of the text display area of W,
3074 without mode lines. Include in this box the left and right
3076 window_box (w
, -1, &x
, &y
, &width
, &height
);
3078 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3079 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3080 bottom_y
= y
+ height
;
3084 /* Scrolling up. Make sure we don't copy part of the mode
3085 line at the bottom. */
3086 if (from_y
+ run
->height
> bottom_y
)
3087 height
= bottom_y
- from_y
;
3089 height
= run
->height
;
3093 /* Scolling down. Make sure we don't copy over the mode line.
3095 if (to_y
+ run
->height
> bottom_y
)
3096 height
= bottom_y
- to_y
;
3098 height
= run
->height
;
3103 /* Cursor off. Will be switched on again in x_update_window_end. */
3107 XCopyArea (FRAME_X_DISPLAY (f
),
3108 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3109 f
->output_data
.x
->normal_gc
,
3119 /***********************************************************************
3121 ***********************************************************************/
3128 /* We used to only do this if Vx_no_window_manager was non-nil, but
3129 the ICCCM (section 4.1.6) says that the window's border pixmap
3130 and border pixel are window attributes which are "private to the
3131 client", so we can always change it to whatever we want. */
3133 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3134 f
->output_data
.x
->border_pixel
);
3136 x_update_cursor (f
, 1);
3140 frame_unhighlight (f
)
3143 /* We used to only do this if Vx_no_window_manager was non-nil, but
3144 the ICCCM (section 4.1.6) says that the window's border pixmap
3145 and border pixel are window attributes which are "private to the
3146 client", so we can always change it to whatever we want. */
3148 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3149 f
->output_data
.x
->border_tile
);
3151 x_update_cursor (f
, 1);
3154 /* The focus has changed. Update the frames as necessary to reflect
3155 the new situation. Note that we can't change the selected frame
3156 here, because the Lisp code we are interrupting might become confused.
3157 Each event gets marked with the frame in which it occurred, so the
3158 Lisp code can tell when the switch took place by examining the events. */
3161 x_new_focus_frame (dpyinfo
, frame
)
3162 struct x_display_info
*dpyinfo
;
3163 struct frame
*frame
;
3165 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3167 if (frame
!= dpyinfo
->x_focus_frame
)
3169 /* Set this before calling other routines, so that they see
3170 the correct value of x_focus_frame. */
3171 dpyinfo
->x_focus_frame
= frame
;
3173 if (old_focus
&& old_focus
->auto_lower
)
3174 x_lower_frame (old_focus
);
3177 selected_frame
= frame
;
3178 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3180 Fselect_window (selected_frame
->selected_window
, Qnil
);
3181 choose_minibuf_frame ();
3184 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3185 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3187 pending_autoraise_frame
= 0;
3190 x_frame_rehighlight (dpyinfo
);
3193 /* Handle FocusIn and FocusOut state changes for FRAME.
3194 If FRAME has focus and there exists more than one frame, puts
3195 a FOCUS_IN_EVENT into *BUFP. */
3198 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
3201 struct x_display_info
*dpyinfo
;
3202 struct frame
*frame
;
3203 struct input_event
*bufp
;
3205 if (type
== FocusIn
)
3207 if (dpyinfo
->x_focus_event_frame
!= frame
)
3209 x_new_focus_frame (dpyinfo
, frame
);
3210 dpyinfo
->x_focus_event_frame
= frame
;
3212 /* Don't stop displaying the initial startup message
3213 for a switch-frame event we don't need. */
3214 if (GC_NILP (Vterminal_frame
)
3215 && GC_CONSP (Vframe_list
)
3216 && !GC_NILP (XCDR (Vframe_list
)))
3218 bufp
->kind
= FOCUS_IN_EVENT
;
3219 XSETFRAME (bufp
->frame_or_window
, frame
);
3223 frame
->output_data
.x
->focus_state
|= state
;
3226 if (FRAME_XIC (frame
))
3227 XSetICFocus (FRAME_XIC (frame
));
3230 else if (type
== FocusOut
)
3232 frame
->output_data
.x
->focus_state
&= ~state
;
3234 if (dpyinfo
->x_focus_event_frame
== frame
)
3236 dpyinfo
->x_focus_event_frame
= 0;
3237 x_new_focus_frame (dpyinfo
, 0);
3241 if (FRAME_XIC (frame
))
3242 XUnsetICFocus (FRAME_XIC (frame
));
3247 /* The focus may have changed. Figure out if it is a real focus change,
3248 by checking both FocusIn/Out and Enter/LeaveNotify events.
3250 Returns FOCUS_IN_EVENT event in *BUFP. */
3253 x_detect_focus_change (dpyinfo
, event
, bufp
)
3254 struct x_display_info
*dpyinfo
;
3256 struct input_event
*bufp
;
3258 struct frame
*frame
;
3260 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3264 switch (event
->type
)
3269 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3271 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3273 if (event
->xcrossing
.detail
!= NotifyInferior
3274 && event
->xcrossing
.focus
3275 && ! (focus_state
& FOCUS_EXPLICIT
))
3276 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3278 dpyinfo
, frame
, bufp
);
3284 x_focus_changed (event
->type
,
3285 (event
->xfocus
.detail
== NotifyPointer
?
3286 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3287 dpyinfo
, frame
, bufp
);
3293 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3296 x_mouse_leave (dpyinfo
)
3297 struct x_display_info
*dpyinfo
;
3299 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3302 /* The focus has changed, or we have redirected a frame's focus to
3303 another frame (this happens when a frame uses a surrogate
3304 mini-buffer frame). Shift the highlight as appropriate.
3306 The FRAME argument doesn't necessarily have anything to do with which
3307 frame is being highlighted or un-highlighted; we only use it to find
3308 the appropriate X display info. */
3311 XTframe_rehighlight (frame
)
3312 struct frame
*frame
;
3314 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3318 x_frame_rehighlight (dpyinfo
)
3319 struct x_display_info
*dpyinfo
;
3321 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3323 if (dpyinfo
->x_focus_frame
)
3325 dpyinfo
->x_highlight_frame
3326 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3327 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3328 : dpyinfo
->x_focus_frame
);
3329 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3331 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3332 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3336 dpyinfo
->x_highlight_frame
= 0;
3338 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3341 frame_unhighlight (old_highlight
);
3342 if (dpyinfo
->x_highlight_frame
)
3343 frame_highlight (dpyinfo
->x_highlight_frame
);
3349 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3351 /* Initialize mode_switch_bit and modifier_meaning. */
3353 x_find_modifier_meanings (dpyinfo
)
3354 struct x_display_info
*dpyinfo
;
3356 int min_code
, max_code
;
3359 XModifierKeymap
*mods
;
3361 dpyinfo
->meta_mod_mask
= 0;
3362 dpyinfo
->shift_lock_mask
= 0;
3363 dpyinfo
->alt_mod_mask
= 0;
3364 dpyinfo
->super_mod_mask
= 0;
3365 dpyinfo
->hyper_mod_mask
= 0;
3368 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3370 min_code
= dpyinfo
->display
->min_keycode
;
3371 max_code
= dpyinfo
->display
->max_keycode
;
3374 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3375 min_code
, max_code
- min_code
+ 1,
3377 mods
= XGetModifierMapping (dpyinfo
->display
);
3379 /* Scan the modifier table to see which modifier bits the Meta and
3380 Alt keysyms are on. */
3382 int row
, col
; /* The row and column in the modifier table. */
3384 for (row
= 3; row
< 8; row
++)
3385 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3388 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3390 /* Zeroes are used for filler. Skip them. */
3394 /* Are any of this keycode's keysyms a meta key? */
3398 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3400 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3406 dpyinfo
->meta_mod_mask
|= (1 << row
);
3411 dpyinfo
->alt_mod_mask
|= (1 << row
);
3416 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3421 dpyinfo
->super_mod_mask
|= (1 << row
);
3425 /* Ignore this if it's not on the lock modifier. */
3426 if ((1 << row
) == LockMask
)
3427 dpyinfo
->shift_lock_mask
= LockMask
;
3435 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3436 if (! dpyinfo
->meta_mod_mask
)
3438 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3439 dpyinfo
->alt_mod_mask
= 0;
3442 /* If some keys are both alt and meta,
3443 make them just meta, not alt. */
3444 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3446 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3449 XFree ((char *) syms
);
3450 XFreeModifiermap (mods
);
3453 /* Convert between the modifier bits X uses and the modifier bits
3457 x_x_to_emacs_modifiers (dpyinfo
, state
)
3458 struct x_display_info
*dpyinfo
;
3461 EMACS_UINT mod_meta
= meta_modifier
;
3462 EMACS_UINT mod_alt
= alt_modifier
;
3463 EMACS_UINT mod_hyper
= hyper_modifier
;
3464 EMACS_UINT mod_super
= super_modifier
;
3467 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3468 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3469 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3470 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3471 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3472 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3473 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3474 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3477 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3478 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3479 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3480 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3481 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3482 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3486 x_emacs_to_x_modifiers (dpyinfo
, state
)
3487 struct x_display_info
*dpyinfo
;
3490 EMACS_UINT mod_meta
= meta_modifier
;
3491 EMACS_UINT mod_alt
= alt_modifier
;
3492 EMACS_UINT mod_hyper
= hyper_modifier
;
3493 EMACS_UINT mod_super
= super_modifier
;
3497 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3498 if (! EQ (tem
, Qnil
)) mod_alt
= XUINT (tem
);
3499 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3500 if (! EQ (tem
, Qnil
)) mod_meta
= XUINT (tem
);
3501 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3502 if (! EQ (tem
, Qnil
)) mod_hyper
= XUINT (tem
);
3503 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3504 if (! EQ (tem
, Qnil
)) mod_super
= XUINT (tem
);
3507 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3508 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3509 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3510 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3511 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3512 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3515 /* Convert a keysym to its name. */
3518 x_get_keysym_name (keysym
)
3524 value
= XKeysymToString (keysym
);
3532 /* Mouse clicks and mouse movement. Rah. */
3534 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3536 If the event is a button press, then note that we have grabbed
3540 construct_mouse_click (result
, event
, f
)
3541 struct input_event
*result
;
3542 XButtonEvent
*event
;
3545 /* Make the event type NO_EVENT; we'll change that when we decide
3547 result
->kind
= MOUSE_CLICK_EVENT
;
3548 result
->code
= event
->button
- Button1
;
3549 result
->timestamp
= event
->time
;
3550 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3552 | (event
->type
== ButtonRelease
3556 XSETINT (result
->x
, event
->x
);
3557 XSETINT (result
->y
, event
->y
);
3558 XSETFRAME (result
->frame_or_window
, f
);
3564 /* Function to report a mouse movement to the mainstream Emacs code.
3565 The input handler calls this.
3567 We have received a mouse movement event, which is given in *event.
3568 If the mouse is over a different glyph than it was last time, tell
3569 the mainstream emacs code by setting mouse_moved. If not, ask for
3570 another motion event, so we can check again the next time it moves. */
3572 static XMotionEvent last_mouse_motion_event
;
3573 static Lisp_Object last_mouse_motion_frame
;
3576 note_mouse_movement (frame
, event
)
3578 XMotionEvent
*event
;
3580 last_mouse_movement_time
= event
->time
;
3581 last_mouse_motion_event
= *event
;
3582 XSETFRAME (last_mouse_motion_frame
, frame
);
3584 if (event
->window
!= FRAME_X_WINDOW (frame
))
3586 frame
->mouse_moved
= 1;
3587 last_mouse_scroll_bar
= Qnil
;
3588 note_mouse_highlight (frame
, -1, -1);
3591 /* Has the mouse moved off the glyph it was on at the last sighting? */
3592 else if (event
->x
< last_mouse_glyph
.x
3593 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3594 || event
->y
< last_mouse_glyph
.y
3595 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3597 frame
->mouse_moved
= 1;
3598 last_mouse_scroll_bar
= Qnil
;
3599 note_mouse_highlight (frame
, event
->x
, event
->y
);
3604 /************************************************************************
3606 ************************************************************************/
3609 redo_mouse_highlight ()
3611 if (!NILP (last_mouse_motion_frame
)
3612 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3613 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3614 last_mouse_motion_event
.x
,
3615 last_mouse_motion_event
.y
);
3619 static int glyph_rect
P_ ((struct frame
*f
, int, int, XRectangle
*));
3622 /* Try to determine frame pixel position and size of the glyph under
3623 frame pixel coordinates X/Y on frame F . Return the position and
3624 size in *RECT. Value is non-zero if we could compute these
3628 glyph_rect (f
, x
, y
, rect
)
3635 struct glyph_row
*r
, *end_row
;
3637 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3641 w
= XWINDOW (window
);
3642 r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3643 end_row
= r
+ w
->current_matrix
->nrows
- 1;
3645 for (; r
< end_row
&& r
->enabled_p
; ++r
)
3649 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3650 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3652 while (g
< end
&& gx
< x
)
3653 gx
+= g
->pixel_width
, ++g
;
3656 rect
->width
= g
->pixel_width
;
3657 rect
->height
= r
->height
;
3658 rect
->x
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3659 rect
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3670 /* Return the current position of the mouse.
3671 *FP should be a frame which indicates which display to ask about.
3673 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3674 and *PART to the frame, window, and scroll bar part that the mouse
3675 is over. Set *X and *Y to the portion and whole of the mouse's
3676 position on the scroll bar.
3678 If the mouse movement started elsewhere, set *FP to the frame the
3679 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3682 Set *TIME to the server time-stamp for the time at which the mouse
3683 was at this position.
3685 Don't store anything if we don't have a valid set of values to report.
3687 This clears the mouse_moved flag, so we can wait for the next mouse
3691 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3694 Lisp_Object
*bar_window
;
3695 enum scroll_bar_part
*part
;
3697 unsigned long *time
;
3703 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3704 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3710 Window dummy_window
;
3713 Lisp_Object frame
, tail
;
3715 /* Clear the mouse-moved flag for every frame on this display. */
3716 FOR_EACH_FRAME (tail
, frame
)
3717 if (FRAME_X_P (XFRAME (frame
))
3718 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3719 XFRAME (frame
)->mouse_moved
= 0;
3721 last_mouse_scroll_bar
= Qnil
;
3723 /* Figure out which root window we're on. */
3724 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3725 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3727 /* The root window which contains the pointer. */
3730 /* Trash which we can't trust if the pointer is on
3731 a different screen. */
3734 /* The position on that root window. */
3737 /* More trash we can't trust. */
3740 /* Modifier keys and pointer buttons, about which
3742 (unsigned int *) &dummy
);
3744 /* Now we have a position on the root; find the innermost window
3745 containing the pointer. */
3749 int parent_x
= 0, parent_y
= 0;
3754 /* XTranslateCoordinates can get errors if the window
3755 structure is changing at the same time this function
3756 is running. So at least we must not crash from them. */
3758 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
3760 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3761 && FRAME_LIVE_P (last_mouse_frame
))
3763 /* If mouse was grabbed on a frame, give coords for that frame
3764 even if the mouse is now outside it. */
3765 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3767 /* From-window, to-window. */
3768 root
, FRAME_X_WINDOW (last_mouse_frame
),
3770 /* From-position, to-position. */
3771 root_x
, root_y
, &win_x
, &win_y
,
3775 f1
= last_mouse_frame
;
3781 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3783 /* From-window, to-window. */
3786 /* From-position, to-position. */
3787 root_x
, root_y
, &win_x
, &win_y
,
3792 if (child
== None
|| child
== win
)
3800 /* Now we know that:
3801 win is the innermost window containing the pointer
3802 (XTC says it has no child containing the pointer),
3803 win_x and win_y are the pointer's position in it
3804 (XTC did this the last time through), and
3805 parent_x and parent_y are the pointer's position in win's parent.
3806 (They are what win_x and win_y were when win was child.
3807 If win is the root window, it has no parent, and
3808 parent_{x,y} are invalid, but that's okay, because we'll
3809 never use them in that case.) */
3811 /* Is win one of our frames? */
3812 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
3814 #ifdef USE_X_TOOLKIT
3815 /* If we end up with the menu bar window, say it's not
3818 && f1
->output_data
.x
->menubar_widget
3819 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
3821 #endif /* USE_X_TOOLKIT */
3824 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
3827 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
3829 /* If not, is it one of our scroll bars? */
3832 struct scroll_bar
*bar
;
3834 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
3838 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3844 if (f1
== 0 && insist
> 0)
3845 f1
= SELECTED_FRAME ();
3849 /* Ok, we found a frame. Store all the values.
3850 last_mouse_glyph is a rectangle used to reduce the
3851 generation of mouse events. To not miss any motion
3852 events, we must divide the frame into rectangles of the
3853 size of the smallest character that could be displayed
3854 on it, i.e. into the same rectangles that matrices on
3855 the frame are divided into. */
3857 int width
, height
, gx
, gy
;
3860 if (glyph_rect (f1
, win_x
, win_y
, &rect
))
3861 last_mouse_glyph
= rect
;
3864 width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3865 height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3869 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3870 round down even for negative values. */
3875 gx
= (gx
+ width
- 1) / width
* width
;
3876 gy
= (gy
+ height
- 1) / height
* height
;
3878 last_mouse_glyph
.width
= width
;
3879 last_mouse_glyph
.height
= height
;
3880 last_mouse_glyph
.x
= gx
;
3881 last_mouse_glyph
.y
= gy
;
3887 XSETINT (*x
, win_x
);
3888 XSETINT (*y
, win_y
);
3889 *time
= last_mouse_movement_time
;
3899 /***********************************************************************
3901 ***********************************************************************/
3903 /* Scroll bar support. */
3905 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
3907 This can be called in GC, so we have to make sure to strip off mark
3910 static struct scroll_bar
*
3911 x_window_to_scroll_bar (display
, window_id
)
3918 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
3919 #endif /* USE_GTK */
3921 for (tail
= Vframe_list
;
3922 XGCTYPE (tail
) == Lisp_Cons
;
3925 Lisp_Object frame
, bar
, condemned
;
3927 frame
= XCAR (tail
);
3928 /* All elements of Vframe_list should be frames. */
3929 if (! GC_FRAMEP (frame
))
3932 if (! FRAME_X_P (XFRAME (frame
)))
3935 /* Scan this frame's scroll bar list for a scroll bar with the
3937 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3938 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3939 /* This trick allows us to search both the ordinary and
3940 condemned scroll bar lists with one loop. */
3941 ! GC_NILP (bar
) || (bar
= condemned
,
3944 bar
= XSCROLL_BAR (bar
)->next
)
3945 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
&&
3946 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
3947 return XSCROLL_BAR (bar
);
3954 #if defined USE_LUCID
3956 /* Return the Lucid menu bar WINDOW is part of. Return null
3957 if WINDOW is not part of a menu bar. */
3960 x_window_to_menu_bar (window
)
3965 for (tail
= Vframe_list
;
3966 XGCTYPE (tail
) == Lisp_Cons
;
3969 if (FRAME_X_P (XFRAME (XCAR (tail
))))
3971 Lisp_Object frame
= XCAR (tail
);
3972 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
3974 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
3982 #endif /* USE_LUCID */
3985 /************************************************************************
3987 ************************************************************************/
3989 #ifdef USE_TOOLKIT_SCROLL_BARS
3991 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
3992 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
3993 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
3994 struct scroll_bar
*));
3995 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
3999 /* Lisp window being scrolled. Set when starting to interact with
4000 a toolkit scroll bar, reset to nil when ending the interaction. */
4002 static Lisp_Object window_being_scrolled
;
4004 /* Last scroll bar part sent in xm_scroll_callback. */
4006 static int last_scroll_bar_part
;
4008 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4009 that movements of 1/20 of the screen size are mapped to up/down. */
4012 /* Id of action hook installed for scroll bars. */
4014 static XtActionHookId action_hook_id
;
4016 static Boolean xaw3d_arrow_scroll
;
4018 /* Whether the drag scrolling maintains the mouse at the top of the
4019 thumb. If not, resizing the thumb needs to be done more carefully
4020 to avoid jerkyness. */
4022 static Boolean xaw3d_pick_top
;
4024 extern void set_vertical_scroll_bar
P_ ((struct window
*));
4026 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4027 bars are used.. The hook is responsible for detecting when
4028 the user ends an interaction with the scroll bar, and generates
4029 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4032 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
4035 XtPointer client_data
;
4039 Cardinal
*num_params
;
4045 scroll_bar_p
= XmIsScrollBar (widget
);
4046 end_action
= "Release";
4047 #else /* !USE_MOTIF i.e. use Xaw */
4048 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4049 end_action
= "EndScroll";
4050 #endif /* USE_MOTIF */
4053 && strcmp (action_name
, end_action
) == 0
4054 && WINDOWP (window_being_scrolled
))
4058 x_send_scroll_bar_event (window_being_scrolled
,
4059 scroll_bar_end_scroll
, 0, 0);
4060 w
= XWINDOW (window_being_scrolled
);
4062 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4064 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4065 /* The thumb size is incorrect while dragging: fix it. */
4066 set_vertical_scroll_bar (w
);
4068 window_being_scrolled
= Qnil
;
4069 last_scroll_bar_part
= -1;
4071 /* Xt timeouts no longer needed. */
4072 toolkit_scroll_bar_interaction
= 0;
4075 #endif /* not USE_GTK */
4077 /* A vector of windows used for communication between
4078 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4080 static struct window
**scroll_bar_windows
;
4081 static int scroll_bar_windows_size
;
4084 /* Send a client message with message type Xatom_Scrollbar for a
4085 scroll action to the frame of WINDOW. PART is a value identifying
4086 the part of the scroll bar that was clicked on. PORTION is the
4087 amount to scroll of a whole of WHOLE. */
4090 x_send_scroll_bar_event (window
, part
, portion
, whole
)
4092 int part
, portion
, whole
;
4095 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4096 struct window
*w
= XWINDOW (window
);
4097 struct frame
*f
= XFRAME (w
->frame
);
4102 /* Construct a ClientMessage event to send to the frame. */
4103 ev
->type
= ClientMessage
;
4104 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4105 ev
->display
= FRAME_X_DISPLAY (f
);
4106 ev
->window
= FRAME_X_WINDOW (f
);
4109 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4110 not enough to store a pointer or Lisp_Object on a 64 bit system.
4111 So, store the window in scroll_bar_windows and pass the index
4112 into that array in the event. */
4113 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4114 if (scroll_bar_windows
[i
] == NULL
)
4117 if (i
== scroll_bar_windows_size
)
4119 int new_size
= max (10, 2 * scroll_bar_windows_size
);
4120 size_t nbytes
= new_size
* sizeof *scroll_bar_windows
;
4121 size_t old_nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4123 scroll_bar_windows
= (struct window
**) xrealloc (scroll_bar_windows
,
4125 bzero (&scroll_bar_windows
[i
], nbytes
- old_nbytes
);
4126 scroll_bar_windows_size
= new_size
;
4129 scroll_bar_windows
[i
] = w
;
4130 ev
->data
.l
[0] = (long) i
;
4131 ev
->data
.l
[1] = (long) part
;
4132 ev
->data
.l
[2] = (long) 0;
4133 ev
->data
.l
[3] = (long) portion
;
4134 ev
->data
.l
[4] = (long) whole
;
4136 /* Make Xt timeouts work while the scroll bar is active. */
4137 toolkit_scroll_bar_interaction
= 1;
4139 /* Setting the event mask to zero means that the message will
4140 be sent to the client that created the window, and if that
4141 window no longer exists, no event will be sent. */
4142 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4147 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4151 x_scroll_bar_to_input_event (event
, ievent
)
4153 struct input_event
*ievent
;
4155 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4160 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4161 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4163 XSETWINDOW (window
, w
);
4164 f
= XFRAME (w
->frame
);
4166 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4167 ievent
->frame_or_window
= window
;
4170 ievent
->timestamp
= CurrentTime
;
4172 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
4174 ievent
->part
= ev
->data
.l
[1];
4175 ievent
->code
= ev
->data
.l
[2];
4176 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4177 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4178 ievent
->modifiers
= 0;
4184 /* Minimum and maximum values used for Motif scroll bars. */
4186 #define XM_SB_MAX 10000000
4189 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4190 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4191 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4194 xm_scroll_callback (widget
, client_data
, call_data
)
4196 XtPointer client_data
, call_data
;
4198 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4199 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4200 int part
= -1, whole
= 0, portion
= 0;
4204 case XmCR_DECREMENT
:
4205 bar
->dragging
= Qnil
;
4206 part
= scroll_bar_up_arrow
;
4209 case XmCR_INCREMENT
:
4210 bar
->dragging
= Qnil
;
4211 part
= scroll_bar_down_arrow
;
4214 case XmCR_PAGE_DECREMENT
:
4215 bar
->dragging
= Qnil
;
4216 part
= scroll_bar_above_handle
;
4219 case XmCR_PAGE_INCREMENT
:
4220 bar
->dragging
= Qnil
;
4221 part
= scroll_bar_below_handle
;
4225 bar
->dragging
= Qnil
;
4226 part
= scroll_bar_to_top
;
4229 case XmCR_TO_BOTTOM
:
4230 bar
->dragging
= Qnil
;
4231 part
= scroll_bar_to_bottom
;
4238 /* Get the slider size. */
4240 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4243 whole
= XM_SB_MAX
- slider_size
;
4244 portion
= min (cs
->value
, whole
);
4245 part
= scroll_bar_handle
;
4246 bar
->dragging
= make_number (cs
->value
);
4250 case XmCR_VALUE_CHANGED
:
4256 window_being_scrolled
= bar
->window
;
4257 last_scroll_bar_part
= part
;
4258 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4263 #else /* !USE_MOTIF, i.e. Xaw or GTK */
4265 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4266 bar widget. DATA is a pointer to the scroll_bar structure. */
4269 xg_scroll_callback (widget
, data
)
4273 struct scroll_bar
*bar
= (struct scroll_bar
*) data
;
4279 int part
= -1, whole
= 0, portion
= 0;
4280 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (widget
));
4282 if (xg_ignore_gtk_scrollbar
) return;
4284 position
= gtk_adjustment_get_value (adj
);
4286 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
4289 p
= (gdouble
*) xmalloc (sizeof (gdouble
));
4291 g_object_set_data (G_OBJECT (widget
), XG_LAST_SB_DATA
, p
);
4297 diff
= (int) (position
- previous
);
4299 if (diff
== (int) adj
->step_increment
)
4301 part
= scroll_bar_down_arrow
;
4302 bar
->dragging
= Qnil
;
4304 else if (-diff
== (int) adj
->step_increment
)
4306 part
= scroll_bar_up_arrow
;
4307 bar
->dragging
= Qnil
;
4309 else if (diff
== (int) adj
->page_increment
)
4311 part
= scroll_bar_below_handle
;
4312 bar
->dragging
= Qnil
;
4314 else if (-diff
== (int) adj
->page_increment
)
4316 part
= scroll_bar_above_handle
;
4317 bar
->dragging
= Qnil
;
4321 part
= scroll_bar_handle
;
4322 whole
= adj
->upper
- adj
->page_size
;
4323 portion
= min ((int)position
, whole
);
4324 bar
->dragging
= make_number ((int)portion
);
4329 window_being_scrolled
= bar
->window
;
4330 last_scroll_bar_part
= part
;
4331 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4335 #else /* not USE_GTK */
4337 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4338 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4339 scroll bar struct. CALL_DATA is a pointer to a float saying where
4343 xaw_jump_callback (widget
, client_data
, call_data
)
4345 XtPointer client_data
, call_data
;
4347 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4348 float top
= *(float *) call_data
;
4350 int whole
, portion
, height
;
4353 /* Get the size of the thumb, a value between 0 and 1. */
4355 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4359 portion
= shown
< 1 ? top
* whole
: 0;
4361 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
4362 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4363 the bottom, so we force the scrolling whenever we see that we're
4364 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4365 we try to ensure that we always stay two pixels away from the
4367 part
= scroll_bar_down_arrow
;
4369 part
= scroll_bar_handle
;
4371 window_being_scrolled
= bar
->window
;
4372 bar
->dragging
= make_number (portion
);
4373 last_scroll_bar_part
= part
;
4374 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4378 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4379 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4380 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4381 the scroll bar. CALL_DATA is an integer specifying the action that
4382 has taken place. Its magnitude is in the range 0..height of the
4383 scroll bar. Negative values mean scroll towards buffer start.
4384 Values < height of scroll bar mean line-wise movement. */
4387 xaw_scroll_callback (widget
, client_data
, call_data
)
4389 XtPointer client_data
, call_data
;
4391 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4392 /* The position really is stored cast to a pointer. */
4393 int position
= (long) call_data
;
4397 /* Get the height of the scroll bar. */
4399 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4402 if (abs (position
) >= height
)
4403 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4405 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4406 it maps line-movement to call_data = max(5, height/20). */
4407 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
4408 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4410 part
= scroll_bar_move_ratio
;
4412 window_being_scrolled
= bar
->window
;
4413 bar
->dragging
= Qnil
;
4414 last_scroll_bar_part
= part
;
4415 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4418 #endif /* not USE_GTK */
4419 #endif /* not USE_MOTIF */
4421 #define SCROLL_BAR_NAME "verticalScrollBar"
4423 /* Create the widget for scroll bar BAR on frame F. Record the widget
4424 and X window of the scroll bar in BAR. */
4428 x_create_toolkit_scroll_bar (f
, bar
)
4430 struct scroll_bar
*bar
;
4432 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4435 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4440 #else /* not USE_GTK */
4443 x_create_toolkit_scroll_bar (f
, bar
)
4445 struct scroll_bar
*bar
;
4451 char *scroll_bar_name
= SCROLL_BAR_NAME
;
4452 unsigned long pixel
;
4457 /* Set resources. Create the widget. */
4458 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4459 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4460 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4461 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4462 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4463 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4464 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4466 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4469 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4473 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4476 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4480 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4481 scroll_bar_name
, av
, ac
);
4483 /* Add one callback for everything that can happen. */
4484 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4486 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4488 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4490 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4492 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4494 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4496 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4499 /* Realize the widget. Only after that is the X window created. */
4500 XtRealizeWidget (widget
);
4502 /* Set the cursor to an arrow. I didn't find a resource to do that.
4503 And I'm wondering why it hasn't an arrow cursor by default. */
4504 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4505 f
->output_data
.x
->nontext_cursor
);
4507 #else /* !USE_MOTIF i.e. use Xaw */
4509 /* Set resources. Create the widget. The background of the
4510 Xaw3d scroll bar widget is a little bit light for my taste.
4511 We don't alter it here to let users change it according
4512 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4513 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4514 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4515 /* For smoother scrolling with Xaw3d -sm */
4516 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4518 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4521 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4525 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4528 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4532 /* Top/bottom shadow colors. */
4534 /* Allocate them, if necessary. */
4535 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4537 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4538 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4539 &pixel
, 1.2, 0x8000))
4541 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4543 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4545 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4546 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4547 &pixel
, 0.6, 0x4000))
4549 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4552 /* Tell the toolkit about them. */
4553 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4554 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4555 /* We tried to allocate a color for the top/bottom shadow, and
4556 failed, so tell Xaw3d to use dithering instead. */
4558 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
);
4562 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4563 be more consistent with other emacs 3d colors, and since Xaw3d is
4564 not good at dealing with allocation failure. */
4566 /* This tells Xaw3d to use real colors instead of dithering for
4568 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4571 /* Specify the colors. */
4572 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4575 XtSetArg (av
[ac
], "topShadowPixel", pixel
);
4578 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4581 XtSetArg (av
[ac
], "bottomShadowPixel", pixel
);
4586 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4587 f
->output_data
.x
->edit_widget
, av
, ac
);
4591 char *val
= initial
;
4592 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4593 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4595 { /* ARROW_SCROLL */
4596 xaw3d_arrow_scroll
= True
;
4597 /* Isn't that just a personal preference ? -sm */
4598 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4602 /* Define callbacks. */
4603 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4604 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4607 /* Realize the widget. Only after that is the X window created. */
4608 XtRealizeWidget (widget
);
4610 #endif /* !USE_MOTIF */
4612 /* Install an action hook that lets us detect when the user
4613 finishes interacting with a scroll bar. */
4614 if (action_hook_id
== 0)
4615 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4617 /* Remember X window and widget in the scroll bar vector. */
4618 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4619 xwindow
= XtWindow (widget
);
4620 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
4624 #endif /* not USE_GTK */
4627 /* Set the thumb size and position of scroll bar BAR. We are currently
4628 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4632 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4633 struct scroll_bar
*bar
;
4634 int portion
, position
, whole
;
4636 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4639 #else /* not USE_GTK */
4641 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4642 struct scroll_bar
*bar
;
4643 int portion
, position
, whole
;
4645 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4646 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4653 /* We use an estimate of 30 chars per line rather than the real
4654 `portion' value. This has the disadvantage that the thumb size
4655 is not very representative, but it makes our life a lot easier.
4656 Otherwise, we have to constantly adjust the thumb size, which
4657 we can't always do quickly enough: while dragging, the size of
4658 the thumb might prevent the user from dragging the thumb all the
4659 way to the end. but Motif and some versions of Xaw3d don't allow
4660 updating the thumb size while dragging. Also, even if we can update
4661 its size, the update will often happen too late.
4662 If you don't believe it, check out revision 1.650 of xterm.c to see
4663 what hoops we were going through and the still poor behavior we got. */
4664 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4665 /* When the thumb is at the bottom, position == whole.
4666 So we need to increase `whole' to make space for the thumb. */
4673 top
= (float) position
/ whole
;
4674 shown
= (float) portion
/ whole
;
4677 if (NILP (bar
->dragging
))
4681 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4682 is the scroll bar's maximum and MIN is the scroll bar's minimum
4684 size
= shown
* XM_SB_MAX
;
4685 size
= min (size
, XM_SB_MAX
);
4686 size
= max (size
, 1);
4688 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4689 value
= top
* XM_SB_MAX
;
4690 value
= min (value
, XM_SB_MAX
- size
);
4692 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4694 #else /* !USE_MOTIF i.e. use Xaw */
4700 top
= (float) position
/ whole
;
4701 shown
= (float) portion
/ whole
;
4705 float old_top
, old_shown
;
4707 XtVaGetValues (widget
,
4708 XtNtopOfThumb
, &old_top
,
4709 XtNshown
, &old_shown
,
4713 /* Massage the top+shown values. */
4714 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4715 top
= max (0, min (1, top
));
4718 /* Keep two pixels available for moving the thumb down. */
4719 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
4721 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4722 check that your system's configuration file contains a define
4723 for `NARROWPROTO'. See s/freebsd.h for an example. */
4724 if (top
!= old_top
|| shown
!= old_shown
)
4726 if (NILP (bar
->dragging
))
4727 XawScrollbarSetThumb (widget
, top
, shown
);
4731 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
4732 int scroll_mode
= 0;
4734 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
4735 if (xaw3d_arrow_scroll
)
4737 /* Xaw3d stupidly ignores resize requests while dragging
4738 so we have to make it believe it's not in dragging mode. */
4739 scroll_mode
= sb
->scrollbar
.scroll_mode
;
4740 if (scroll_mode
== 2)
4741 sb
->scrollbar
.scroll_mode
= 0;
4744 /* Try to make the scrolling a tad smoother. */
4745 if (!xaw3d_pick_top
)
4746 shown
= min (shown
, old_shown
);
4748 XawScrollbarSetThumb (widget
, top
, shown
);
4751 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
4752 sb
->scrollbar
.scroll_mode
= scroll_mode
;
4757 #endif /* !USE_MOTIF */
4761 #endif /* not USE_GTK */
4763 #endif /* USE_TOOLKIT_SCROLL_BARS */
4767 /************************************************************************
4768 Scroll bars, general
4769 ************************************************************************/
4771 /* Create a scroll bar and return the scroll bar vector for it. W is
4772 the Emacs window on which to create the scroll bar. TOP, LEFT,
4773 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4776 static struct scroll_bar
*
4777 x_scroll_bar_create (w
, top
, left
, width
, height
)
4779 int top
, left
, width
, height
;
4781 struct frame
*f
= XFRAME (w
->frame
);
4782 struct scroll_bar
*bar
4783 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4787 #ifdef USE_TOOLKIT_SCROLL_BARS
4788 x_create_toolkit_scroll_bar (f
, bar
);
4789 #else /* not USE_TOOLKIT_SCROLL_BARS */
4791 XSetWindowAttributes a
;
4795 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4796 if (a
.background_pixel
== -1)
4797 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
4799 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4800 | ButtonMotionMask
| PointerMotionHintMask
4802 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4804 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
4806 /* Clear the area of W that will serve as a scroll bar. This is
4807 for the case that a window has been split horizontally. In
4808 this case, no clear_frame is generated to reduce flickering. */
4809 if (width
> 0 && height
> 0)
4810 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4812 window_box_height (w
), False
);
4814 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4815 /* Position and size of scroll bar. */
4816 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4818 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4820 /* Border width, depth, class, and visual. */
4827 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
4829 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4831 XSETWINDOW (bar
->window
, w
);
4832 XSETINT (bar
->top
, top
);
4833 XSETINT (bar
->left
, left
);
4834 XSETINT (bar
->width
, width
);
4835 XSETINT (bar
->height
, height
);
4836 XSETINT (bar
->start
, 0);
4837 XSETINT (bar
->end
, 0);
4838 bar
->dragging
= Qnil
;
4840 /* Add bar to its frame's list of scroll bars. */
4841 bar
->next
= FRAME_SCROLL_BARS (f
);
4843 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4844 if (!NILP (bar
->next
))
4845 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4847 /* Map the window/widget. */
4848 #ifdef USE_TOOLKIT_SCROLL_BARS
4851 xg_update_scrollbar_pos (f
,
4852 SCROLL_BAR_X_WINDOW (bar
),
4854 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4855 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4859 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar
));
4860 #else /* not USE_GTK */
4861 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4862 XtConfigureWidget (scroll_bar
,
4863 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4865 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4866 max (height
, 1), 0);
4867 XtMapWidget (scroll_bar
);
4868 #endif /* not USE_GTK */
4870 #else /* not USE_TOOLKIT_SCROLL_BARS */
4871 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
4872 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4879 /* Draw BAR's handle in the proper position.
4881 If the handle is already drawn from START to END, don't bother
4882 redrawing it, unless REBUILD is non-zero; in that case, always
4883 redraw it. (REBUILD is handy for drawing the handle after expose
4886 Normally, we want to constrain the start and end of the handle to
4887 fit inside its rectangle, but if the user is dragging the scroll
4888 bar handle, we want to let them drag it down all the way, so that
4889 the bar's top is as far down as it goes; otherwise, there's no way
4890 to move to the very end of the buffer. */
4892 #ifndef USE_TOOLKIT_SCROLL_BARS
4895 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4896 struct scroll_bar
*bar
;
4900 int dragging
= ! NILP (bar
->dragging
);
4901 Window w
= SCROLL_BAR_X_WINDOW (bar
);
4902 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4903 GC gc
= f
->output_data
.x
->normal_gc
;
4905 /* If the display is already accurate, do nothing. */
4907 && start
== XINT (bar
->start
)
4908 && end
== XINT (bar
->end
))
4914 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
4915 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
4916 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4918 /* Make sure the values are reasonable, and try to preserve
4919 the distance between start and end. */
4921 int length
= end
- start
;
4925 else if (start
> top_range
)
4927 end
= start
+ length
;
4931 else if (end
> top_range
&& ! dragging
)
4935 /* Store the adjusted setting in the scroll bar. */
4936 XSETINT (bar
->start
, start
);
4937 XSETINT (bar
->end
, end
);
4939 /* Clip the end position, just for display. */
4940 if (end
> top_range
)
4943 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
4944 below top positions, to make sure the handle is always at least
4945 that many pixels tall. */
4946 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4948 /* Draw the empty space above the handle. Note that we can't clear
4949 zero-height areas; that means "clear to end of window." */
4951 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4952 /* x, y, width, height, and exposures. */
4953 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4954 VERTICAL_SCROLL_BAR_TOP_BORDER
,
4955 inside_width
, start
,
4958 /* Change to proper foreground color if one is specified. */
4959 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4960 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4961 f
->output_data
.x
->scroll_bar_foreground_pixel
);
4963 /* Draw the handle itself. */
4964 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
4965 /* x, y, width, height */
4966 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4967 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
4968 inside_width
, end
- start
);
4970 /* Restore the foreground color of the GC if we changed it above. */
4971 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
4972 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
4973 f
->output_data
.x
->foreground_pixel
);
4975 /* Draw the empty space below the handle. Note that we can't
4976 clear zero-height areas; that means "clear to end of window." */
4977 if (end
< inside_height
)
4978 x_clear_area (FRAME_X_DISPLAY (f
), w
,
4979 /* x, y, width, height, and exposures. */
4980 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
4981 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
4982 inside_width
, inside_height
- end
,
4990 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4992 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4996 x_scroll_bar_remove (bar
)
4997 struct scroll_bar
*bar
;
4999 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5002 #ifdef USE_TOOLKIT_SCROLL_BARS
5004 xg_remove_scroll_bar (f
, SCROLL_BAR_X_WINDOW (bar
));
5005 #else /* not USE_GTK */
5006 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
5007 #endif /* not USE_GTK */
5009 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
5012 /* Disassociate this scroll bar from its window. */
5013 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5019 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5020 that we are displaying PORTION characters out of a total of WHOLE
5021 characters, starting at POSITION. If WINDOW has no scroll bar,
5025 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
5027 int portion
, whole
, position
;
5029 struct frame
*f
= XFRAME (w
->frame
);
5030 struct scroll_bar
*bar
;
5031 int top
, height
, left
, sb_left
, width
, sb_width
;
5032 int window_y
, window_height
;
5034 /* Get window dimensions. */
5035 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5037 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5038 height
= window_height
;
5040 /* Compute the left edge of the scroll bar area. */
5041 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5043 /* Compute the width of the scroll bar which might be less than
5044 the width of the area reserved for the scroll bar. */
5045 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5046 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5050 /* Compute the left edge of the scroll bar. */
5051 #ifdef USE_TOOLKIT_SCROLL_BARS
5052 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5053 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
5055 sb_left
= left
+ (width
- sb_width
) / 2;
5057 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5058 sb_left
= left
+ width
- sb_width
;
5063 /* Does the scroll bar exist yet? */
5064 if (NILP (w
->vertical_scroll_bar
))
5066 if (width
> 0 && height
> 0)
5069 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5070 left
, top
, width
, height
, False
);
5074 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5078 /* It may just need to be moved and resized. */
5079 unsigned int mask
= 0;
5081 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5085 if (sb_left
!= XINT (bar
->left
))
5087 if (top
!= XINT (bar
->top
))
5089 if (sb_width
!= XINT (bar
->width
))
5091 if (height
!= XINT (bar
->height
))
5094 #ifdef USE_TOOLKIT_SCROLL_BARS
5098 xg_update_scrollbar_pos (f
,
5099 SCROLL_BAR_X_WINDOW (bar
),
5101 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5102 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5106 #else /* not USE_GTK */
5108 /* Since toolkit scroll bars are smaller than the space reserved
5109 for them on the frame, we have to clear "under" them. */
5110 if (width
> 0 && height
> 0)
5111 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5112 left
, top
, width
, height
, False
);
5113 /* Move/size the scroll bar widget. */
5115 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5116 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5118 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5119 max (height
, 1), 0);
5121 #endif /* not USE_GTK */
5122 #else /* not USE_TOOLKIT_SCROLL_BARS */
5124 /* Clear areas not covered by the scroll bar because of
5125 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5126 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5128 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5129 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5131 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5132 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5133 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5137 /* Clear areas not covered by the scroll bar because it's not as
5138 wide as the area reserved for it. This makes sure a
5139 previous mode line display is cleared after C-x 2 C-x 1, for
5142 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5143 int rest
= area_width
- sb_width
;
5144 if (rest
> 0 && height
> 0)
5146 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5147 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5148 left
+ area_width
- rest
, top
,
5149 rest
, height
, False
);
5151 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5152 left
, top
, rest
, height
, False
);
5156 /* Move/size the scroll bar window. */
5161 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5163 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5165 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
5169 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5171 /* Remember new settings. */
5172 XSETINT (bar
->left
, sb_left
);
5173 XSETINT (bar
->top
, top
);
5174 XSETINT (bar
->width
, sb_width
);
5175 XSETINT (bar
->height
, height
);
5180 #ifdef USE_TOOLKIT_SCROLL_BARS
5181 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5182 #else /* not USE_TOOLKIT_SCROLL_BARS */
5183 /* Set the scroll bar's current state, unless we're currently being
5185 if (NILP (bar
->dragging
))
5187 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5190 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5193 int start
= ((double) position
* top_range
) / whole
;
5194 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5195 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5198 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5200 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5204 /* The following three hooks are used when we're doing a thorough
5205 redisplay of the frame. We don't explicitly know which scroll bars
5206 are going to be deleted, because keeping track of when windows go
5207 away is a real pain - "Can you say set-window-configuration, boys
5208 and girls?" Instead, we just assert at the beginning of redisplay
5209 that *all* scroll bars are to be removed, and then save a scroll bar
5210 from the fiery pit when we actually redisplay its window. */
5212 /* Arrange for all scroll bars on FRAME to be removed at the next call
5213 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5214 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5217 XTcondemn_scroll_bars (frame
)
5220 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5221 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5224 bar
= FRAME_SCROLL_BARS (frame
);
5225 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5226 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5227 XSCROLL_BAR (bar
)->prev
= Qnil
;
5228 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5229 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5230 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5235 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5236 Note that WINDOW isn't necessarily condemned at all. */
5239 XTredeem_scroll_bar (window
)
5240 struct window
*window
;
5242 struct scroll_bar
*bar
;
5245 /* We can't redeem this window's scroll bar if it doesn't have one. */
5246 if (NILP (window
->vertical_scroll_bar
))
5249 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5251 /* Unlink it from the condemned list. */
5252 f
= XFRAME (WINDOW_FRAME (window
));
5253 if (NILP (bar
->prev
))
5255 /* If the prev pointer is nil, it must be the first in one of
5257 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5258 /* It's not condemned. Everything's fine. */
5260 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5261 window
->vertical_scroll_bar
))
5262 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5264 /* If its prev pointer is nil, it must be at the front of
5265 one or the other! */
5269 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5271 if (! NILP (bar
->next
))
5272 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5274 bar
->next
= FRAME_SCROLL_BARS (f
);
5276 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5277 if (! NILP (bar
->next
))
5278 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5281 /* Remove all scroll bars on FRAME that haven't been saved since the
5282 last call to `*condemn_scroll_bars_hook'. */
5285 XTjudge_scroll_bars (f
)
5288 Lisp_Object bar
, next
;
5290 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5292 /* Clear out the condemned list now so we won't try to process any
5293 more events on the hapless scroll bars. */
5294 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5296 for (; ! NILP (bar
); bar
= next
)
5298 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5300 x_scroll_bar_remove (b
);
5303 b
->next
= b
->prev
= Qnil
;
5306 /* Now there should be no references to the condemned scroll bars,
5307 and they should get garbage-collected. */
5311 #ifndef USE_TOOLKIT_SCROLL_BARS
5312 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5313 is a no-op when using toolkit scroll bars.
5315 This may be called from a signal handler, so we have to ignore GC
5319 x_scroll_bar_expose (bar
, event
)
5320 struct scroll_bar
*bar
;
5323 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5324 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5325 GC gc
= f
->output_data
.x
->normal_gc
;
5326 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5330 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
5332 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5333 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5335 /* x, y, width, height */
5337 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
5338 XINT (bar
->height
) - 1);
5343 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5345 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5346 is set to something other than NO_EVENT, it is enqueued.
5348 This may be called from a signal handler, so we have to ignore GC
5353 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
5354 struct scroll_bar
*bar
;
5356 struct input_event
*emacs_event
;
5358 if (! GC_WINDOWP (bar
->window
))
5361 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5362 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5363 emacs_event
->modifiers
5364 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5365 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5366 event
->xbutton
.state
)
5367 | (event
->type
== ButtonRelease
5370 emacs_event
->frame_or_window
= bar
->window
;
5371 emacs_event
->arg
= Qnil
;
5372 emacs_event
->timestamp
= event
->xbutton
.time
;
5375 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5377 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5380 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5381 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5384 if (y
> top_range
) y
= top_range
;
5386 if (y
< XINT (bar
->start
))
5387 emacs_event
->part
= scroll_bar_above_handle
;
5388 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5389 emacs_event
->part
= scroll_bar_handle
;
5391 emacs_event
->part
= scroll_bar_below_handle
;
5393 /* Just because the user has clicked on the handle doesn't mean
5394 they want to drag it. Lisp code needs to be able to decide
5395 whether or not we're dragging. */
5397 /* If the user has just clicked on the handle, record where they're
5399 if (event
->type
== ButtonPress
5400 && emacs_event
->part
== scroll_bar_handle
)
5401 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
5404 #ifndef USE_TOOLKIT_SCROLL_BARS
5405 /* If the user has released the handle, set it to its final position. */
5406 if (event
->type
== ButtonRelease
5407 && ! NILP (bar
->dragging
))
5409 int new_start
= y
- XINT (bar
->dragging
);
5410 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5412 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5413 bar
->dragging
= Qnil
;
5417 /* Same deal here as the other #if 0. */
5419 /* Clicks on the handle are always reported as occurring at the top of
5421 if (emacs_event
->part
== scroll_bar_handle
)
5422 emacs_event
->x
= bar
->start
;
5424 XSETINT (emacs_event
->x
, y
);
5426 XSETINT (emacs_event
->x
, y
);
5429 XSETINT (emacs_event
->y
, top_range
);
5433 #ifndef USE_TOOLKIT_SCROLL_BARS
5435 /* Handle some mouse motion while someone is dragging the scroll bar.
5437 This may be called from a signal handler, so we have to ignore GC
5441 x_scroll_bar_note_movement (bar
, event
)
5442 struct scroll_bar
*bar
;
5445 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5447 last_mouse_movement_time
= event
->xmotion
.time
;
5450 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5452 /* If we're dragging the bar, display it. */
5453 if (! GC_NILP (bar
->dragging
))
5455 /* Where should the handle be now? */
5456 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5458 if (new_start
!= XINT (bar
->start
))
5460 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5462 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5467 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5469 /* Return information to the user about the current position of the mouse
5470 on the scroll bar. */
5473 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5475 Lisp_Object
*bar_window
;
5476 enum scroll_bar_part
*part
;
5478 unsigned long *time
;
5480 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5481 Window w
= SCROLL_BAR_X_WINDOW (bar
);
5482 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5484 Window dummy_window
;
5486 unsigned int dummy_mask
;
5490 /* Get the mouse's position relative to the scroll bar window, and
5492 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5494 /* Root, child, root x and root y. */
5495 &dummy_window
, &dummy_window
,
5496 &dummy_coord
, &dummy_coord
,
5498 /* Position relative to scroll bar. */
5501 /* Mouse buttons and modifier keys. */
5508 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
5511 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5513 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5515 if (! NILP (bar
->dragging
))
5516 win_y
-= XINT (bar
->dragging
);
5520 if (win_y
> top_range
)
5524 *bar_window
= bar
->window
;
5526 if (! NILP (bar
->dragging
))
5527 *part
= scroll_bar_handle
;
5528 else if (win_y
< XINT (bar
->start
))
5529 *part
= scroll_bar_above_handle
;
5530 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5531 *part
= scroll_bar_handle
;
5533 *part
= scroll_bar_below_handle
;
5535 XSETINT (*x
, win_y
);
5536 XSETINT (*y
, top_range
);
5539 last_mouse_scroll_bar
= Qnil
;
5542 *time
= last_mouse_movement_time
;
5548 /* The screen has been cleared so we may have changed foreground or
5549 background colors, and the scroll bars may need to be redrawn.
5550 Clear out the scroll bars, and ask for expose events, so we can
5554 x_scroll_bar_clear (f
)
5557 #ifndef USE_TOOLKIT_SCROLL_BARS
5560 /* We can have scroll bars even if this is 0,
5561 if we just turned off scroll bar mode.
5562 But in that case we should not clear them. */
5563 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5564 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5565 bar
= XSCROLL_BAR (bar
)->next
)
5566 XClearArea (FRAME_X_DISPLAY (f
),
5567 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
5569 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5573 /* Define a queue to save up SelectionRequest events for later handling. */
5575 struct selection_event_queue
5578 struct selection_event_queue
*next
;
5581 static struct selection_event_queue
*queue
;
5583 /* Nonzero means queue up certain events--don't process them yet. */
5585 static int x_queue_selection_requests
;
5587 /* Queue up an X event *EVENT, to be processed later. */
5590 x_queue_event (f
, event
)
5594 struct selection_event_queue
*queue_tmp
5595 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
5597 if (queue_tmp
!= NULL
)
5599 queue_tmp
->event
= *event
;
5600 queue_tmp
->next
= queue
;
5605 /* Take all the queued events and put them back
5606 so that they get processed afresh. */
5609 x_unqueue_events (display
)
5612 while (queue
!= NULL
)
5614 struct selection_event_queue
*queue_tmp
= queue
;
5615 XPutBackEvent (display
, &queue_tmp
->event
);
5616 queue
= queue_tmp
->next
;
5617 xfree ((char *)queue_tmp
);
5621 /* Start queuing SelectionRequest events. */
5624 x_start_queuing_selection_requests (display
)
5627 x_queue_selection_requests
++;
5630 /* Stop queuing SelectionRequest events. */
5633 x_stop_queuing_selection_requests (display
)
5636 x_queue_selection_requests
--;
5637 x_unqueue_events (display
);
5640 /* The main X event-reading loop - XTread_socket. */
5643 /* Time stamp of enter window event. This is only used by XTread_socket,
5644 but we have to put it out here, since static variables within functions
5645 sometimes don't work. */
5647 static Time enter_timestamp
;
5650 /* This holds the state XLookupString needs to implement dead keys
5651 and other tricks known as "compose processing". _X Window System_
5652 says that a portable program can't use this, but Stephen Gildea assures
5653 me that letting the compiler initialize it to zeros will work okay.
5655 This must be defined outside of XTread_socket, for the same reasons
5656 given for enter_timestamp, above. */
5658 static XComposeStatus compose_status
;
5660 /* Record the last 100 characters stored
5661 to help debug the loss-of-chars-during-GC problem. */
5663 static int temp_index
;
5664 static short temp_buffer
[100];
5666 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5667 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5669 temp_buffer[temp_index++] = (keysym)
5671 /* Set this to nonzero to fake an "X I/O error"
5672 on a particular display. */
5674 struct x_display_info
*XTread_socket_fake_io_error
;
5676 /* When we find no input here, we occasionally do a no-op command
5677 to verify that the X server is still running and we can still talk with it.
5678 We try all the open displays, one by one.
5679 This variable is used for cycling thru the displays. */
5681 static struct x_display_info
*next_noop_dpyinfo
;
5683 #define SET_SAVED_MENU_EVENT(size) \
5686 if (f->output_data.x->saved_menu_event == 0) \
5687 f->output_data.x->saved_menu_event \
5688 = (XEvent *) xmalloc (sizeof (XEvent)); \
5689 bcopy (&event, f->output_data.x->saved_menu_event, size); \
5690 inev.kind = MENU_BAR_ACTIVATE_EVENT; \
5691 XSETFRAME (inev.frame_or_window, f); \
5695 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5696 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5706 /* Filter events for the current X input method.
5707 DPYINFO is the display this event is for.
5708 EVENT is the X event to filter.
5710 Returns non-zero if the event was filtered, caller shall not process
5712 Returns zero if event is wasn't filtered. */
5716 x_filter_event (dpyinfo
, event
)
5717 struct x_display_info
*dpyinfo
;
5720 /* XFilterEvent returns non-zero if the input method has
5721 consumed the event. We pass the frame's X window to
5722 XFilterEvent because that's the one for which the IC
5725 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5726 event
->xclient
.window
);
5728 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5733 static int current_count
;
5734 static int current_finish
;
5735 static struct input_event
*current_hold_quit
;
5737 /* This is the filter function invoked by the GTK event loop.
5738 It is invoked before the XEvent is translated to a GdkEvent,
5739 so we have a chance to act on the event before GTK. */
5740 static GdkFilterReturn
5741 event_handler_gdk (gxev
, ev
, data
)
5746 XEvent
*xev
= (XEvent
*) gxev
;
5748 if (current_count
>= 0)
5750 struct x_display_info
*dpyinfo
;
5752 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5755 /* Filter events for the current X input method.
5756 GTK calls XFilterEvent but not for key press and release,
5757 so we do it here. */
5758 if (xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5759 if (dpyinfo
&& x_filter_event (dpyinfo
, xev
))
5760 return GDK_FILTER_REMOVE
;
5764 current_finish
= X_EVENT_NORMAL
;
5768 handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5773 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5775 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5776 return GDK_FILTER_REMOVE
;
5778 return GDK_FILTER_CONTINUE
;
5780 #endif /* USE_GTK */
5783 /* Handles the XEvent EVENT on display DPYINFO.
5785 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5786 *FINISH is zero if caller should continue reading events.
5787 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5789 We return the number of characters stored into the buffer. */
5792 handle_one_xevent (dpyinfo
, eventp
, finish
, hold_quit
)
5793 struct x_display_info
*dpyinfo
;
5796 struct input_event
*hold_quit
;
5798 struct input_event inev
;
5803 struct coding_system coding
;
5804 XEvent event
= *eventp
;
5806 *finish
= X_EVENT_NORMAL
;
5809 inev
.kind
= NO_EVENT
;
5816 if (event
.xclient
.message_type
5817 == dpyinfo
->Xatom_wm_protocols
5818 && event
.xclient
.format
== 32)
5820 if (event
.xclient
.data
.l
[0]
5821 == dpyinfo
->Xatom_wm_take_focus
)
5823 /* Use x_any_window_to_frame because this
5824 could be the shell widget window
5825 if the frame has no title bar. */
5826 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5828 /* Not quite sure this is needed -pd */
5829 if (f
&& FRAME_XIC (f
))
5830 XSetICFocus (FRAME_XIC (f
));
5832 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5833 instructs the WM to set the input focus automatically for
5834 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5835 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5836 it has set the focus. So, XSetInputFocus below is not
5839 The call to XSetInputFocus below has also caused trouble. In
5840 cases where the XSetInputFocus done by the WM and the one
5841 below are temporally close (on a fast machine), the call
5842 below can generate additional FocusIn events which confuse
5845 /* Since we set WM_TAKE_FOCUS, we must call
5846 XSetInputFocus explicitly. But not if f is null,
5847 since that might be an event for a deleted frame. */
5850 Display
*d
= event
.xclient
.display
;
5851 /* Catch and ignore errors, in case window has been
5852 iconified by a window manager such as GWM. */
5853 int count
= x_catch_errors (d
);
5854 XSetInputFocus (d
, event
.xclient
.window
,
5855 /* The ICCCM says this is
5856 the only valid choice. */
5858 event
.xclient
.data
.l
[1]);
5859 /* This is needed to detect the error
5860 if there is an error. */
5862 x_uncatch_errors (d
, count
);
5864 /* Not certain about handling scroll bars here */
5869 if (event
.xclient
.data
.l
[0]
5870 == dpyinfo
->Xatom_wm_save_yourself
)
5872 /* Save state modify the WM_COMMAND property to
5873 something which can reinstate us. This notifies
5874 the session manager, who's looking for such a
5875 PropertyNotify. Can restart processing when
5876 a keyboard or mouse event arrives. */
5877 /* If we have a session manager, don't set this.
5878 KDE will then start two Emacsen, one for the
5879 session manager and one for this. */
5881 if (! x_session_have_connection ())
5884 f
= x_top_window_to_frame (dpyinfo
,
5885 event
.xclient
.window
);
5886 /* This is just so we only give real data once
5887 for a single Emacs process. */
5888 if (f
== SELECTED_FRAME ())
5889 XSetCommand (FRAME_X_DISPLAY (f
),
5890 event
.xclient
.window
,
5891 initial_argv
, initial_argc
);
5893 XSetCommand (FRAME_X_DISPLAY (f
),
5894 event
.xclient
.window
,
5900 if (event
.xclient
.data
.l
[0]
5901 == dpyinfo
->Xatom_wm_delete_window
)
5903 f
= x_any_window_to_frame (dpyinfo
,
5904 event
.xclient
.window
);
5906 goto OTHER
; /* May be a dialog that is to be removed */
5908 inev
.kind
= DELETE_WINDOW_EVENT
;
5909 XSETFRAME (inev
.frame_or_window
, f
);
5916 if (event
.xclient
.message_type
5917 == dpyinfo
->Xatom_wm_configure_denied
)
5922 if (event
.xclient
.message_type
5923 == dpyinfo
->Xatom_wm_window_moved
)
5926 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5928 new_x
= event
.xclient
.data
.s
[0];
5929 new_y
= event
.xclient
.data
.s
[1];
5933 f
->left_pos
= new_x
;
5940 if (event
.xclient
.message_type
5941 == dpyinfo
->Xatom_editres
)
5943 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5944 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
5948 #endif /* HACK_EDITRES */
5950 if ((event
.xclient
.message_type
5951 == dpyinfo
->Xatom_DONE
)
5952 || (event
.xclient
.message_type
5953 == dpyinfo
->Xatom_PAGE
))
5955 /* Ghostview job completed. Kill it. We could
5956 reply with "Next" if we received "Page", but we
5957 currently never do because we are interested in
5958 images, only, which should have 1 page. */
5959 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
5960 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
5961 x_kill_gs_process (pixmap
, f
);
5962 expose_frame (f
, 0, 0, 0, 0);
5966 #ifdef USE_TOOLKIT_SCROLL_BARS
5967 /* Scroll bar callbacks send a ClientMessage from which
5968 we construct an input_event. */
5969 if (event
.xclient
.message_type
5970 == dpyinfo
->Xatom_Scrollbar
)
5972 x_scroll_bar_to_input_event (&event
, &inev
);
5973 *finish
= X_EVENT_GOTO_OUT
;
5976 #endif /* USE_TOOLKIT_SCROLL_BARS */
5978 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5983 if (x_handle_dnd_message (f
, &event
.xclient
, dpyinfo
, &inev
))
5984 *finish
= X_EVENT_DROP
;
5988 case SelectionNotify
:
5989 #ifdef USE_X_TOOLKIT
5990 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
5992 #endif /* not USE_X_TOOLKIT */
5993 x_handle_selection_notify (&event
.xselection
);
5996 case SelectionClear
: /* Someone has grabbed ownership. */
5997 #ifdef USE_X_TOOLKIT
5998 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
6000 #endif /* USE_X_TOOLKIT */
6002 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
6004 inev
.kind
= SELECTION_CLEAR_EVENT
;
6005 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
6006 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
6007 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
6008 inev
.frame_or_window
= Qnil
;
6012 case SelectionRequest
: /* Someone wants our selection. */
6013 #ifdef USE_X_TOOLKIT
6014 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
6016 #endif /* USE_X_TOOLKIT */
6017 if (x_queue_selection_requests
)
6018 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
6022 XSelectionRequestEvent
*eventp
6023 = (XSelectionRequestEvent
*) &event
;
6025 inev
.kind
= SELECTION_REQUEST_EVENT
;
6026 SELECTION_EVENT_DISPLAY (&inev
) = eventp
->display
;
6027 SELECTION_EVENT_REQUESTOR (&inev
) = eventp
->requestor
;
6028 SELECTION_EVENT_SELECTION (&inev
) = eventp
->selection
;
6029 SELECTION_EVENT_TARGET (&inev
) = eventp
->target
;
6030 SELECTION_EVENT_PROPERTY (&inev
) = eventp
->property
;
6031 SELECTION_EVENT_TIME (&inev
) = eventp
->time
;
6032 inev
.frame_or_window
= Qnil
;
6036 case PropertyNotify
:
6037 #if 0 /* This is plain wrong. In the case that we are waiting for a
6038 PropertyNotify used as an ACK in incremental selection
6039 transfer, the property will be on the receiver's window. */
6040 #if defined USE_X_TOOLKIT
6041 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
6045 x_handle_property_notify (&event
.xproperty
);
6048 case ReparentNotify
:
6049 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
6053 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
6054 x_real_positions (f
, &x
, &y
);
6058 /* Perhaps reparented due to a WM restart. Reset this. */
6059 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6064 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
6067 x_check_fullscreen (f
);
6069 if (f
->async_visible
== 0)
6071 f
->async_visible
= 1;
6072 f
->async_iconified
= 0;
6073 f
->output_data
.x
->has_been_visible
= 1;
6074 SET_FRAME_GARBAGED (f
);
6078 event
.xexpose
.x
, event
.xexpose
.y
,
6079 event
.xexpose
.width
, event
.xexpose
.height
);
6083 #ifndef USE_TOOLKIT_SCROLL_BARS
6084 struct scroll_bar
*bar
;
6086 #if defined USE_LUCID
6087 /* Submenus of the Lucid menu bar aren't widgets
6088 themselves, so there's no way to dispatch events
6089 to them. Recognize this case separately. */
6092 = x_window_to_menu_bar (event
.xexpose
.window
);
6094 xlwmenu_redisplay (widget
);
6096 #endif /* USE_LUCID */
6098 #ifdef USE_TOOLKIT_SCROLL_BARS
6099 /* Dispatch event to the widget. */
6101 #else /* not USE_TOOLKIT_SCROLL_BARS */
6102 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6103 event
.xexpose
.window
);
6106 x_scroll_bar_expose (bar
, &event
);
6107 #ifdef USE_X_TOOLKIT
6110 #endif /* USE_X_TOOLKIT */
6111 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6115 case GraphicsExpose
: /* This occurs when an XCopyArea's
6116 source area was obscured or not
6118 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6122 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6123 event
.xgraphicsexpose
.width
,
6124 event
.xgraphicsexpose
.height
);
6126 #ifdef USE_X_TOOLKIT
6129 #endif /* USE_X_TOOLKIT */
6132 case NoExpose
: /* This occurs when an XCopyArea's
6133 source area was completely
6138 /* Redo the mouse-highlight after the tooltip has gone. */
6139 if (event
.xmap
.window
== tip_window
)
6142 redo_mouse_highlight ();
6145 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6146 if (f
) /* F may no longer exist if
6147 the frame was deleted. */
6149 /* While a frame is unmapped, display generation is
6150 disabled; you don't want to spend time updating a
6151 display that won't ever be seen. */
6152 f
->async_visible
= 0;
6153 /* We can't distinguish, from the event, whether the window
6154 has become iconified or invisible. So assume, if it
6155 was previously visible, than now it is iconified.
6156 But x_make_frame_invisible clears both
6157 the visible flag and the iconified flag;
6158 and that way, we know the window is not iconified now. */
6159 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6161 f
->async_iconified
= 1;
6163 inev
.kind
= ICONIFY_EVENT
;
6164 XSETFRAME (inev
.frame_or_window
, f
);
6170 if (event
.xmap
.window
== tip_window
)
6171 /* The tooltip has been drawn already. Avoid
6172 the SET_FRAME_GARBAGED below. */
6175 /* We use x_top_window_to_frame because map events can
6176 come for sub-windows and they don't mean that the
6177 frame is visible. */
6178 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6181 /* wait_reading_process_output will notice this and update
6182 the frame's display structures.
6183 If we where iconified, we should not set garbaged,
6184 because that stops redrawing on Expose events. This looks
6185 bad if we are called from a recursive event loop
6186 (x_dispatch_event), for example when a dialog is up. */
6187 if (! f
->async_iconified
)
6188 SET_FRAME_GARBAGED (f
);
6190 f
->async_visible
= 1;
6191 f
->async_iconified
= 0;
6192 f
->output_data
.x
->has_been_visible
= 1;
6196 inev
.kind
= DEICONIFY_EVENT
;
6197 XSETFRAME (inev
.frame_or_window
, f
);
6199 else if (! NILP (Vframe_list
)
6200 && ! NILP (XCDR (Vframe_list
)))
6201 /* Force a redisplay sooner or later
6202 to update the frame titles
6203 in case this is the second frame. */
6204 record_asynch_buffer_change ();
6210 ignore_next_mouse_click_timeout
= 0;
6212 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6213 /* Dispatch KeyPress events when in menu. */
6214 if (popup_activated ())
6218 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6220 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6222 clear_mouse_face (dpyinfo
);
6223 dpyinfo
->mouse_face_hidden
= 1;
6226 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6229 /* Scroll bars consume key events, but we want
6230 the keys to go to the scroll bar's frame. */
6231 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6233 if (widget
&& XmIsScrollBar (widget
))
6235 widget
= XtParent (widget
);
6236 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6239 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6243 KeySym keysym
, orig_keysym
;
6244 /* al%imercury@uunet.uu.net says that making this 81
6245 instead of 80 fixed a bug whereby meta chars made
6248 It seems that some version of XmbLookupString has
6249 a bug of not returning XBufferOverflow in
6250 status_return even if the input is too long to
6251 fit in 81 bytes. So, we must prepare sufficient
6252 bytes for copy_buffer. 513 bytes (256 chars for
6253 two-byte character set) seems to be a fairly good
6254 approximation. -- 2000.8.10 handa@etl.go.jp */
6255 unsigned char copy_buffer
[513];
6256 unsigned char *copy_bufptr
= copy_buffer
;
6257 int copy_bufsiz
= sizeof (copy_buffer
);
6259 Lisp_Object coding_system
= Qlatin_1
;
6263 /* Don't pass keys to GTK. A Tab will shift focus to the
6264 tool bar in GTK 2.4. Keys will still go to menus and
6265 dialogs because in that case popup_activated is TRUE
6267 *finish
= X_EVENT_DROP
;
6271 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6272 extra_keyboard_modifiers
);
6273 modifiers
= event
.xkey
.state
;
6275 /* This will have to go some day... */
6277 /* make_lispy_event turns chars into control chars.
6278 Don't do it here because XLookupString is too eager. */
6279 event
.xkey
.state
&= ~ControlMask
;
6280 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6281 | dpyinfo
->super_mod_mask
6282 | dpyinfo
->hyper_mod_mask
6283 | dpyinfo
->alt_mod_mask
);
6285 /* In case Meta is ComposeCharacter,
6286 clear its status. According to Markus Ehrnsperger
6287 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6288 this enables ComposeCharacter to work whether or
6289 not it is combined with Meta. */
6290 if (modifiers
& dpyinfo
->meta_mod_mask
)
6291 bzero (&compose_status
, sizeof (compose_status
));
6296 Status status_return
;
6298 coding_system
= Vlocale_coding_system
;
6299 nbytes
= XmbLookupString (FRAME_XIC (f
),
6300 &event
.xkey
, copy_bufptr
,
6301 copy_bufsiz
, &keysym
,
6303 if (status_return
== XBufferOverflow
)
6305 copy_bufsiz
= nbytes
+ 1;
6306 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6307 nbytes
= XmbLookupString (FRAME_XIC (f
),
6308 &event
.xkey
, copy_bufptr
,
6309 copy_bufsiz
, &keysym
,
6312 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6313 #if 0 && defined X_HAVE_UTF8_STRING
6314 else if (status_return
== XLookupKeySym
)
6315 { /* Try again but with utf-8. */
6316 coding_system
= Qutf_8
;
6317 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6318 &event
.xkey
, copy_bufptr
,
6319 copy_bufsiz
, &keysym
,
6321 if (status_return
== XBufferOverflow
)
6323 copy_bufsiz
= nbytes
+ 1;
6324 copy_bufptr
= (char *) alloca (copy_bufsiz
);
6325 nbytes
= Xutf8LookupString (FRAME_XIC (f
),
6328 copy_bufsiz
, &keysym
,
6334 if (status_return
== XLookupNone
)
6336 else if (status_return
== XLookupChars
)
6341 else if (status_return
!= XLookupKeySym
6342 && status_return
!= XLookupBoth
)
6346 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6347 copy_bufsiz
, &keysym
,
6350 nbytes
= XLookupString (&event
.xkey
, copy_bufptr
,
6351 copy_bufsiz
, &keysym
,
6355 /* If not using XIM/XIC, and a compose sequence is in progress,
6356 we break here. Otherwise, chars_matched is always 0. */
6357 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6360 orig_keysym
= keysym
;
6362 /* Common for all keysym input events. */
6363 XSETFRAME (inev
.frame_or_window
, f
);
6365 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), modifiers
);
6366 inev
.timestamp
= event
.xkey
.time
;
6368 /* First deal with keysyms which have defined
6369 translations to characters. */
6370 if (keysym
>= 32 && keysym
< 128)
6371 /* Avoid explicitly decoding each ASCII character. */
6373 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
6378 /* Now non-ASCII. */
6379 if (HASH_TABLE_P (Vx_keysym_table
)
6380 && (NATNUMP (c
= Fgethash (make_number (keysym
),
6384 inev
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6385 ? ASCII_KEYSTROKE_EVENT
6386 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6387 inev
.code
= XFASTINT (c
);
6391 /* Random non-modifier sorts of keysyms. */
6392 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6393 || keysym
== XK_Delete
6394 #ifdef XK_ISO_Left_Tab
6395 || (keysym
>= XK_ISO_Left_Tab
6396 && keysym
<= XK_ISO_Enter
)
6398 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6399 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6401 /* This recognizes the "extended function
6402 keys". It seems there's no cleaner way.
6403 Test IsModifierKey to avoid handling
6404 mode_switch incorrectly. */
6405 || ((unsigned) (keysym
) >= XK_Select
6406 && (unsigned)(keysym
) < XK_KP_Space
)
6408 #ifdef XK_dead_circumflex
6409 || orig_keysym
== XK_dead_circumflex
6411 #ifdef XK_dead_grave
6412 || orig_keysym
== XK_dead_grave
6414 #ifdef XK_dead_tilde
6415 || orig_keysym
== XK_dead_tilde
6417 #ifdef XK_dead_diaeresis
6418 || orig_keysym
== XK_dead_diaeresis
6420 #ifdef XK_dead_macron
6421 || orig_keysym
== XK_dead_macron
6423 #ifdef XK_dead_degree
6424 || orig_keysym
== XK_dead_degree
6426 #ifdef XK_dead_acute
6427 || orig_keysym
== XK_dead_acute
6429 #ifdef XK_dead_cedilla
6430 || orig_keysym
== XK_dead_cedilla
6432 #ifdef XK_dead_breve
6433 || orig_keysym
== XK_dead_breve
6435 #ifdef XK_dead_ogonek
6436 || orig_keysym
== XK_dead_ogonek
6438 #ifdef XK_dead_caron
6439 || orig_keysym
== XK_dead_caron
6441 #ifdef XK_dead_doubleacute
6442 || orig_keysym
== XK_dead_doubleacute
6444 #ifdef XK_dead_abovedot
6445 || orig_keysym
== XK_dead_abovedot
6447 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6448 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6449 /* Any "vendor-specific" key is ok. */
6450 || (orig_keysym
& (1 << 28))
6451 || (keysym
!= NoSymbol
&& nbytes
== 0))
6452 && ! (IsModifierKey (orig_keysym
)
6454 #ifdef XK_Mode_switch
6455 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
6458 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
6460 #endif /* not HAVE_X11R5 */
6461 /* The symbols from XK_ISO_Lock
6462 to XK_ISO_Last_Group_Lock
6463 don't have real modifiers but
6464 should be treated similarly to
6465 Mode_switch by Emacs. */
6466 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6467 || ((unsigned)(orig_keysym
)
6469 && (unsigned)(orig_keysym
)
6470 <= XK_ISO_Last_Group_Lock
)
6474 STORE_KEYSYM_FOR_DEBUG (keysym
);
6475 /* make_lispy_event will convert this to a symbolic
6477 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6482 { /* Raw bytes, not keysym. */
6487 /* The input should be decoded with `coding_system'
6488 which depends on which X*LookupString function
6489 we used just above and the locale. */
6490 setup_coding_system (coding_system
, &coding
);
6491 coding
.src_multibyte
= 0;
6492 coding
.dst_multibyte
= 1;
6493 /* The input is converted to events, thus we can't
6494 handle composition. Anyway, there's no XIM that
6495 gives us composition information. */
6496 coding
.composing
= COMPOSITION_DISABLED
;
6498 for (i
= 0; i
< nbytes
; i
++)
6500 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6504 /* Decode the input data. */
6508 require
= decoding_buffer_size (&coding
, nbytes
);
6509 p
= (unsigned char *) alloca (require
);
6510 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6511 /* We explicitly disable composition handling because
6512 key data should not contain any composition sequence. */
6513 coding
.composing
= COMPOSITION_DISABLED
;
6514 decode_coding (&coding
, copy_bufptr
, p
, nbytes
, require
);
6515 nbytes
= coding
.produced
;
6516 nchars
= coding
.produced_char
;
6520 /* Convert the input data to a sequence of
6521 character events. */
6522 for (i
= 0; i
< nbytes
; i
+= len
)
6524 if (nchars
== nbytes
)
6525 c
= copy_bufptr
[i
], len
= 1;
6527 c
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
,
6529 inev
.kind
= (SINGLE_BYTE_CHAR_P (c
)
6530 ? ASCII_KEYSTROKE_EVENT
6531 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6533 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6536 /* Previous code updated count by nchars rather than nbytes,
6537 but that seems bogus to me. ++kfs */
6540 inev
.kind
= NO_EVENT
; /* Already stored above. */
6542 if (keysym
== NoSymbol
)
6548 /* Don't dispatch this event since XtDispatchEvent calls
6549 XFilterEvent, and two calls in a row may freeze the
6558 /* Don't dispatch this event since XtDispatchEvent calls
6559 XFilterEvent, and two calls in a row may freeze the
6567 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6569 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6571 if (f
&& x_mouse_click_focus_ignore_position
)
6572 ignore_next_mouse_click_timeout
= event
.xmotion
.time
+ 200;
6575 if (event
.xcrossing
.focus
)
6577 /* Avoid nasty pop/raise loops. */
6578 if (f
&& (!(f
->auto_raise
)
6580 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
6582 x_new_focus_frame (dpyinfo
, f
);
6583 enter_timestamp
= event
.xcrossing
.time
;
6586 else if (f
== dpyinfo
->x_focus_frame
)
6587 x_new_focus_frame (dpyinfo
, 0);
6590 /* EnterNotify counts as mouse movement,
6591 so update things that depend on mouse position. */
6592 if (f
&& !f
->output_data
.x
->hourglass_p
)
6593 note_mouse_movement (f
, &event
.xmotion
);
6597 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6601 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6603 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6606 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6608 /* If we move outside the frame, then we're
6609 certainly no longer on any text in the frame. */
6610 clear_mouse_face (dpyinfo
);
6611 dpyinfo
->mouse_face_mouse_frame
= 0;
6614 /* Generate a nil HELP_EVENT to cancel a help-echo.
6615 Do it only if there's something to cancel.
6616 Otherwise, the startup message is cleared when
6617 the mouse leaves the frame. */
6618 if (any_help_event_p
)
6624 x_detect_focus_change (dpyinfo
, &event
, &inev
);
6629 previous_help_echo_string
= help_echo_string
;
6630 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
6633 if (dpyinfo
->grabbed
&& last_mouse_frame
6634 && FRAME_LIVE_P (last_mouse_frame
))
6635 f
= last_mouse_frame
;
6637 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6639 if (dpyinfo
->mouse_face_hidden
)
6641 dpyinfo
->mouse_face_hidden
= 0;
6642 clear_mouse_face (dpyinfo
);
6648 /* Generate SELECT_WINDOW_EVENTs when needed. */
6649 if (mouse_autoselect_window
)
6653 window
= window_from_coordinates (f
,
6654 event
.xmotion
.x
, event
.xmotion
.y
,
6657 /* Window will be selected only when it is not selected now and
6658 last mouse movement event was not in it. Minibuffer window
6659 will be selected iff it is active. */
6660 if (WINDOWP (window
)
6661 && !EQ (window
, last_window
)
6662 && !EQ (window
, selected_window
))
6664 inev
.kind
= SELECT_WINDOW_EVENT
;
6665 inev
.frame_or_window
= window
;
6670 note_mouse_movement (f
, &event
.xmotion
);
6674 #ifndef USE_TOOLKIT_SCROLL_BARS
6675 struct scroll_bar
*bar
6676 = x_window_to_scroll_bar (event
.xmotion
.display
,
6677 event
.xmotion
.window
);
6680 x_scroll_bar_note_movement (bar
, &event
);
6681 #endif /* USE_TOOLKIT_SCROLL_BARS */
6683 /* If we move outside the frame, then we're
6684 certainly no longer on any text in the frame. */
6685 clear_mouse_face (dpyinfo
);
6688 /* If the contents of the global variable help_echo_string
6689 has changed, generate a HELP_EVENT. */
6690 if (!NILP (help_echo_string
)
6691 || !NILP (previous_help_echo_string
))
6696 case ConfigureNotify
:
6697 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6700 #ifndef USE_X_TOOLKIT
6702 xg_resize_widgets (f
, event
.xconfigure
.width
,
6703 event
.xconfigure
.height
);
6704 #else /* not USE_GTK */
6705 /* If there is a pending resize for fullscreen, don't
6706 do this one, the right one will come later.
6707 The toolkit version doesn't seem to need this, but we
6708 need to reset it below. */
6710 = ((f
->want_fullscreen
& FULLSCREEN_WAIT
)
6711 && f
->new_text_cols
!= 0);
6712 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6713 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6718 /* In the toolkit version, change_frame_size
6719 is called by the code that handles resizing
6720 of the EmacsFrame widget. */
6722 /* Even if the number of character rows and columns has
6723 not changed, the font size may have changed, so we need
6724 to check the pixel dimensions as well. */
6725 if (columns
!= FRAME_COLS (f
)
6726 || rows
!= FRAME_LINES (f
)
6727 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6728 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6730 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6731 SET_FRAME_GARBAGED (f
);
6732 cancel_mouse_face (f
);
6734 #endif /* not USE_GTK */
6737 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6738 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6741 /* GTK creates windows but doesn't map them.
6742 Only get real positions and check fullscreen when mapped. */
6743 if (FRAME_GTK_OUTER_WIDGET (f
)
6744 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f
)))
6747 /* What we have now is the position of Emacs's own window.
6748 Convert that to the position of the window manager window. */
6749 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6751 x_check_expected_move (f
);
6752 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
6753 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6757 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6758 xic_set_statusarea (f
);
6761 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
6763 /* Since the WM decorations come below top_pos now,
6764 we must put them below top_pos in the future. */
6765 f
->win_gravity
= NorthWestGravity
;
6766 x_wm_set_size_hint (f
, (long) 0, 0);
6774 /* If we decide we want to generate an event to be seen
6775 by the rest of Emacs, we put it here. */
6778 bzero (&compose_status
, sizeof (compose_status
));
6780 if (dpyinfo
->grabbed
6782 && FRAME_LIVE_P (last_mouse_frame
))
6783 f
= last_mouse_frame
;
6785 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6789 /* Is this in the tool-bar? */
6790 if (WINDOWP (f
->tool_bar_window
)
6791 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6794 int x
= event
.xbutton
.x
;
6795 int y
= event
.xbutton
.y
;
6797 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
6798 if (EQ (window
, f
->tool_bar_window
))
6800 if (event
.xbutton
.type
== ButtonPress
)
6801 handle_tool_bar_click (f
, x
, y
, 1, 0);
6803 handle_tool_bar_click (f
, x
, y
, 0,
6804 x_x_to_emacs_modifiers (dpyinfo
,
6805 event
.xbutton
.state
));
6811 if (!dpyinfo
->x_focus_frame
6812 || f
== dpyinfo
->x_focus_frame
)
6814 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6815 if (! popup_activated ())
6818 if (ignore_next_mouse_click_timeout
)
6820 if (event
.type
== ButtonPress
6821 && (int)(event
.xbutton
.time
- ignore_next_mouse_click_timeout
) > 0)
6823 ignore_next_mouse_click_timeout
= 0;
6824 construct_mouse_click (&inev
, &event
, f
);
6826 if (event
.type
== ButtonRelease
)
6827 ignore_next_mouse_click_timeout
= 0;
6830 construct_mouse_click (&inev
, &event
, f
);
6836 struct scroll_bar
*bar
6837 = x_window_to_scroll_bar (event
.xbutton
.display
,
6838 event
.xbutton
.window
);
6840 #ifdef USE_TOOLKIT_SCROLL_BARS
6841 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6843 if (bar
&& event
.xbutton
.state
& ControlMask
)
6845 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6846 *finish
= X_EVENT_DROP
;
6848 #else /* not USE_TOOLKIT_SCROLL_BARS */
6850 x_scroll_bar_handle_click (bar
, &event
, &inev
);
6851 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6854 if (event
.type
== ButtonPress
)
6856 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
6857 last_mouse_frame
= f
;
6858 /* Ignore any mouse motion that happened
6859 before this event; any subsequent mouse-movement
6860 Emacs events should reflect only motion after
6866 last_tool_bar_item
= -1;
6869 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
6871 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6872 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6873 /* For a down-event in the menu bar,
6874 don't pass it to Xt right now.
6875 Instead, save it away
6876 and we will pass it to Xt from kbd_buffer_get_event.
6877 That way, we can run some Lisp code first. */
6880 ! popup_activated ()
6883 f
&& event
.type
== ButtonPress
6884 /* Verify the event is really within the menu bar
6885 and not just sent to it due to grabbing. */
6886 && event
.xbutton
.x
>= 0
6887 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
6888 && event
.xbutton
.y
>= 0
6889 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
6890 && event
.xbutton
.same_screen
)
6892 SET_SAVED_BUTTON_EVENT
;
6893 XSETFRAME (last_mouse_press_frame
, f
);
6895 *finish
= X_EVENT_DROP
;
6898 else if (event
.type
== ButtonPress
)
6900 last_mouse_press_frame
= Qnil
;
6904 #ifdef USE_MOTIF /* This should do not harm for Lucid,
6905 but I am trying to be cautious. */
6906 else if (event
.type
== ButtonRelease
)
6908 if (!NILP (last_mouse_press_frame
))
6910 f
= XFRAME (last_mouse_press_frame
);
6911 if (f
->output_data
.x
)
6912 SET_SAVED_BUTTON_EVENT
;
6917 #endif /* USE_MOTIF */
6920 #endif /* USE_X_TOOLKIT || USE_GTK */
6924 case CirculateNotify
:
6927 case CirculateRequest
:
6930 case VisibilityNotify
:
6934 /* Someone has changed the keyboard mapping - update the
6936 switch (event
.xmapping
.request
)
6938 case MappingModifier
:
6939 x_find_modifier_meanings (dpyinfo
);
6940 /* This is meant to fall through. */
6941 case MappingKeyboard
:
6942 XRefreshKeyboardMapping (&event
.xmapping
);
6948 #ifdef USE_X_TOOLKIT
6950 if (*finish
!= X_EVENT_DROP
)
6951 XtDispatchEvent (&event
);
6953 #endif /* USE_X_TOOLKIT */
6958 if (inev
.kind
!= NO_EVENT
)
6960 kbd_buffer_store_event_hold (&inev
, hold_quit
);
6965 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
6970 XSETFRAME (frame
, f
);
6976 any_help_event_p
= 1;
6977 gen_help_event (help_echo_string
, frame
, help_echo_window
,
6978 help_echo_object
, help_echo_pos
);
6982 help_echo_string
= Qnil
;
6983 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
6993 /* Handles the XEvent EVENT on display DISPLAY.
6994 This is used for event loops outside the normal event handling,
6995 i.e. looping while a popup menu or a dialog is posted.
6997 Returns the value handle_one_xevent sets in the finish argument. */
6999 x_dispatch_event (event
, display
)
7003 struct x_display_info
*dpyinfo
;
7004 int finish
= X_EVENT_NORMAL
;
7006 dpyinfo
= x_display_info_for_display (display
);
7009 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
7015 /* Read events coming from the X server.
7016 This routine is called by the SIGIO handler.
7017 We return as soon as there are no more events to be read.
7019 We return the number of characters stored into the buffer,
7020 thus pretending to be `read'.
7022 EXPECTED is nonzero if the caller knows input is available. */
7025 XTread_socket (display
, expected
, hold_quit
)
7026 struct display
*display
;
7028 struct input_event
*hold_quit
;
7032 int event_found
= 0;
7033 struct x_display_info
*dpyinfo
;
7035 if (interrupt_input_blocked
)
7037 interrupt_input_pending
= 1;
7041 interrupt_input_pending
= 0;
7044 /* So people can tell when we have read the available input. */
7045 input_signal_count
++;
7049 /* Find the display we are supposed to read input for.
7050 It's the one communicating on descriptor SD. */
7051 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
7053 #if 0 /* This ought to be unnecessary; let's verify it. */
7055 /* If available, Xlib uses FIOSNBIO to make the socket
7056 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
7057 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7058 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7059 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
7060 #endif /* ! defined (FIOSNBIO) */
7063 #if 0 /* This code can't be made to work, with multiple displays,
7064 and appears not to be used on any system any more.
7065 Also keyboard.c doesn't turn O_NDELAY on and off
7066 for X connections. */
7069 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
7071 extern int read_alarm_should_throw
;
7072 read_alarm_should_throw
= 1;
7073 XPeekEvent (dpyinfo
->display
, &event
);
7074 read_alarm_should_throw
= 0;
7076 #endif /* HAVE_SELECT */
7080 /* For debugging, this gives a way to fake an I/O error. */
7081 if (dpyinfo
== XTread_socket_fake_io_error
)
7083 XTread_socket_fake_io_error
= 0;
7084 x_io_error_quitter (dpyinfo
->display
);
7089 struct input_event inev
;
7091 /* We don't need to EVENT_INIT (inev) here, as
7092 x_session_check_input copies an entire input_event. */
7093 if (x_session_check_input (&inev
))
7095 kbd_buffer_store_event_hold (&inev
, hold_quit
);
7103 while (XPending (dpyinfo
->display
))
7107 XNextEvent (dpyinfo
->display
, &event
);
7110 /* Filter events for the current X input method. */
7111 if (x_filter_event (dpyinfo
, &event
))
7116 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
7118 if (finish
== X_EVENT_GOTO_OUT
)
7121 #endif /* not USE_GTK */
7126 /* For GTK we must use the GTK event loop. But XEvents gets passed
7127 to our filter function above, and then to the big event switch.
7128 We use a bunch of globals to communicate with our filter function,
7129 that is kind of ugly, but it works.
7131 There is no way to do one display at the time, GTK just does events
7132 from all displays. */
7134 while (gtk_events_pending ())
7136 current_count
= count
;
7137 current_hold_quit
= hold_quit
;
7139 gtk_main_iteration ();
7141 count
= current_count
;
7143 current_hold_quit
= 0;
7145 if (current_finish
== X_EVENT_GOTO_OUT
)
7148 #endif /* USE_GTK */
7152 /* On some systems, an X bug causes Emacs to get no more events
7153 when the window is destroyed. Detect that. (1994.) */
7156 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7157 One XNOOP in 100 loops will make Emacs terminate.
7158 B. Bretthauer, 1994 */
7160 if (x_noop_count
>= 100)
7164 if (next_noop_dpyinfo
== 0)
7165 next_noop_dpyinfo
= x_display_list
;
7167 XNoOp (next_noop_dpyinfo
->display
);
7169 /* Each time we get here, cycle through the displays now open. */
7170 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7174 /* If the focus was just given to an auto-raising frame,
7176 /* ??? This ought to be able to handle more than one such frame. */
7177 if (pending_autoraise_frame
)
7179 x_raise_frame (pending_autoraise_frame
);
7180 pending_autoraise_frame
= 0;
7192 /***********************************************************************
7194 ***********************************************************************/
7196 /* Set clipping for output in glyph row ROW. W is the window in which
7197 we operate. GC is the graphics context to set clipping in.
7199 ROW may be a text row or, e.g., a mode line. Text rows must be
7200 clipped to the interior of the window dedicated to text display,
7201 mode lines must be clipped to the whole window. */
7204 x_clip_to_row (w
, row
, gc
)
7206 struct glyph_row
*row
;
7209 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7210 XRectangle clip_rect
;
7211 int window_y
, window_width
;
7213 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
7215 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
7216 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
7217 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7218 clip_rect
.width
= window_width
;
7219 clip_rect
.height
= row
->visible_height
;
7221 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7225 /* Draw a hollow box cursor on window W in glyph row ROW. */
7228 x_draw_hollow_cursor (w
, row
)
7230 struct glyph_row
*row
;
7232 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7233 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7234 Display
*dpy
= FRAME_X_DISPLAY (f
);
7237 struct glyph
*cursor_glyph
;
7240 /* Get the glyph the cursor is on. If we can't tell because
7241 the current matrix is invalid or such, give up. */
7242 cursor_glyph
= get_phys_cursor_glyph (w
);
7243 if (cursor_glyph
== NULL
)
7246 /* Compute the width of the rectangle to draw. If on a stretch
7247 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7248 rectangle as wide as the glyph, but use a canonical character
7250 wd
= cursor_glyph
->pixel_width
- 1;
7251 if (cursor_glyph
->type
== STRETCH_GLYPH
7252 && !x_stretch_cursor_p
)
7253 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
7254 w
->phys_cursor_width
= wd
;
7256 /* Compute frame-relative coordinates from window-relative
7258 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7259 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
);
7261 /* Compute the proper height and ascent of the rectangle, based
7262 on the actual glyph. Using the full height of the row looks
7263 bad when there are tall images on that row. */
7264 h
= max (min (FRAME_LINE_HEIGHT (f
), row
->height
),
7265 cursor_glyph
->ascent
+ cursor_glyph
->descent
);
7266 if (h
< row
->height
)
7267 y
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
7270 /* The foreground of cursor_gc is typically the same as the normal
7271 background color, which can cause the cursor box to be invisible. */
7272 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7273 if (dpyinfo
->scratch_cursor_gc
)
7274 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7276 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7277 GCForeground
, &xgcv
);
7278 gc
= dpyinfo
->scratch_cursor_gc
;
7280 /* Set clipping, draw the rectangle, and reset clipping again. */
7281 x_clip_to_row (w
, row
, gc
);
7282 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
7283 XSetClipMask (dpy
, gc
, None
);
7287 /* Draw a bar cursor on window W in glyph row ROW.
7289 Implementation note: One would like to draw a bar cursor with an
7290 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7291 Unfortunately, I didn't find a font yet that has this property set.
7295 x_draw_bar_cursor (w
, row
, width
, kind
)
7297 struct glyph_row
*row
;
7299 enum text_cursor_kinds kind
;
7301 struct frame
*f
= XFRAME (w
->frame
);
7302 struct glyph
*cursor_glyph
;
7304 /* If cursor is out of bounds, don't draw garbage. This can happen
7305 in mini-buffer windows when switching between echo area glyphs
7307 cursor_glyph
= get_phys_cursor_glyph (w
);
7308 if (cursor_glyph
== NULL
)
7311 /* If on an image, draw like a normal cursor. That's usually better
7312 visible than drawing a bar, esp. if the image is large so that
7313 the bar might not be in the window. */
7314 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7316 struct glyph_row
*row
;
7317 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7318 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7322 Display
*dpy
= FRAME_X_DISPLAY (f
);
7323 Window window
= FRAME_X_WINDOW (f
);
7324 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7325 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7326 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7329 /* If the glyph's background equals the color we normally draw
7330 the bar cursor in, the bar cursor in its normal color is
7331 invisible. Use the glyph's foreground color instead in this
7332 case, on the assumption that the glyph's colors are chosen so
7333 that the glyph is legible. */
7334 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7335 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7337 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7338 xgcv
.graphics_exposures
= 0;
7341 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7344 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7345 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7349 width
= FRAME_CURSOR_WIDTH (f
);
7350 width
= min (cursor_glyph
->pixel_width
, width
);
7352 w
->phys_cursor_width
= width
;
7353 x_clip_to_row (w
, row
, gc
);
7355 if (kind
== BAR_CURSOR
)
7356 XFillRectangle (dpy
, window
, gc
,
7357 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7358 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7359 width
, row
->height
);
7361 XFillRectangle (dpy
, window
, gc
,
7362 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7363 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7364 row
->height
- width
),
7365 cursor_glyph
->pixel_width
,
7368 XSetClipMask (dpy
, gc
, None
);
7373 /* RIF: Define cursor CURSOR on frame F. */
7376 x_define_frame_cursor (f
, cursor
)
7380 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7384 /* RIF: Clear area on frame F. */
7387 x_clear_frame_area (f
, x
, y
, width
, height
)
7389 int x
, y
, width
, height
;
7391 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7392 x
, y
, width
, height
, False
);
7396 /* RIF: Draw cursor on window W. */
7399 x_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
7401 struct glyph_row
*glyph_row
;
7403 int cursor_type
, cursor_width
;
7406 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7410 w
->phys_cursor_type
= cursor_type
;
7411 w
->phys_cursor_on_p
= 1;
7413 if (glyph_row
->exact_window_width_line_p
7414 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
7416 glyph_row
->cursor_in_fringe_p
= 1;
7417 draw_fringe_bitmap (w
, glyph_row
, 0);
7420 switch (cursor_type
)
7422 case HOLLOW_BOX_CURSOR
:
7423 x_draw_hollow_cursor (w
, glyph_row
);
7426 case FILLED_BOX_CURSOR
:
7427 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7431 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7435 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7439 w
->phys_cursor_width
= 0;
7447 if (w
== XWINDOW (f
->selected_window
))
7448 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7449 xic_set_preeditarea (w
, x
, y
);
7454 if (updating_frame
!= f
)
7455 XFlush (FRAME_X_DISPLAY (f
));
7462 /* Make the x-window of frame F use the gnu icon bitmap. */
7465 x_bitmap_icon (f
, file
)
7471 if (FRAME_X_WINDOW (f
) == 0)
7474 /* Free up our existing icon bitmap and mask if any. */
7475 if (f
->output_data
.x
->icon_bitmap
> 0)
7476 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7477 f
->output_data
.x
->icon_bitmap
= 0;
7482 /* Use gtk_window_set_icon_from_file () if available,
7483 It's not restricted to bitmaps */
7484 if (xg_set_icon (f
, file
))
7486 #endif /* USE_GTK */
7487 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7488 x_create_bitmap_mask (f
, bitmap_id
);
7492 /* Create the GNU bitmap and mask if necessary. */
7493 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7495 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
7496 = x_create_bitmap_from_data (f
, gnu_bits
,
7497 gnu_width
, gnu_height
);
7498 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7501 /* The first time we create the GNU bitmap and mask,
7502 this increments the ref-count one extra time.
7503 As a result, the GNU bitmap and mask are never freed.
7504 That way, we don't have to worry about allocating it again. */
7505 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7507 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7510 x_wm_set_icon_pixmap (f
, bitmap_id
);
7511 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7517 /* Make the x-window of frame F use a rectangle with text.
7518 Use ICON_NAME as the text. */
7521 x_text_icon (f
, icon_name
)
7525 if (FRAME_X_WINDOW (f
) == 0)
7531 text
.value
= (unsigned char *) icon_name
;
7532 text
.encoding
= XA_STRING
;
7534 text
.nitems
= strlen (icon_name
);
7535 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7537 #else /* not HAVE_X11R4 */
7538 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), icon_name
);
7539 #endif /* not HAVE_X11R4 */
7541 if (f
->output_data
.x
->icon_bitmap
> 0)
7542 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7543 f
->output_data
.x
->icon_bitmap
= 0;
7544 x_wm_set_icon_pixmap (f
, 0);
7549 #define X_ERROR_MESSAGE_SIZE 200
7551 /* If non-nil, this should be a string.
7552 It means catch X errors and store the error message in this string. */
7554 static Lisp_Object x_error_message_string
;
7556 /* An X error handler which stores the error message in
7557 x_error_message_string. This is called from x_error_handler if
7558 x_catch_errors is in effect. */
7561 x_error_catcher (display
, error
)
7565 XGetErrorText (display
, error
->error_code
,
7566 SDATA (x_error_message_string
),
7567 X_ERROR_MESSAGE_SIZE
);
7570 /* Begin trapping X errors for display DPY. Actually we trap X errors
7571 for all displays, but DPY should be the display you are actually
7574 After calling this function, X protocol errors no longer cause
7575 Emacs to exit; instead, they are recorded in the string
7576 stored in x_error_message_string.
7578 Calling x_check_errors signals an Emacs error if an X error has
7579 occurred since the last call to x_catch_errors or x_check_errors.
7581 Calling x_uncatch_errors resumes the normal error handling. */
7583 void x_check_errors ();
7584 static Lisp_Object
x_catch_errors_unwind ();
7587 x_catch_errors (dpy
)
7590 int count
= SPECPDL_INDEX ();
7592 /* Make sure any errors from previous requests have been dealt with. */
7595 record_unwind_protect (x_catch_errors_unwind
,
7596 Fcons (make_save_value (dpy
, 0),
7597 x_error_message_string
));
7599 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
7600 SSET (x_error_message_string
, 0, 0);
7605 /* Unbind the binding that we made to check for X errors. */
7608 x_catch_errors_unwind (old_val
)
7609 Lisp_Object old_val
;
7611 Lisp_Object first
= XCAR (old_val
);
7612 Display
*dpy
= XSAVE_VALUE (first
)->pointer
;
7614 /* The display may have been closed before this function is called.
7615 Check if it is still open before calling XSync. */
7616 if (x_display_info_for_display (dpy
) != 0)
7619 x_error_message_string
= XCDR (old_val
);
7623 /* If any X protocol errors have arrived since the last call to
7624 x_catch_errors or x_check_errors, signal an Emacs error using
7625 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7628 x_check_errors (dpy
, format
)
7632 /* Make sure to catch any errors incurred so far. */
7635 if (SREF (x_error_message_string
, 0))
7636 error (format
, SDATA (x_error_message_string
));
7639 /* Nonzero if we had any X protocol errors
7640 since we did x_catch_errors on DPY. */
7643 x_had_errors_p (dpy
)
7646 /* Make sure to catch any errors incurred so far. */
7649 return SREF (x_error_message_string
, 0) != 0;
7652 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7655 x_clear_errors (dpy
)
7658 SSET (x_error_message_string
, 0, 0);
7661 /* Stop catching X protocol errors and let them make Emacs die.
7662 DPY should be the display that was passed to x_catch_errors.
7663 COUNT should be the value that was returned by
7664 the corresponding call to x_catch_errors. */
7667 x_uncatch_errors (dpy
, count
)
7671 unbind_to (count
, Qnil
);
7675 static unsigned int x_wire_count
;
7678 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7683 /* Handle SIGPIPE, which can happen when the connection to a server
7684 simply goes away. SIGPIPE is handled by x_connection_signal.
7685 Don't need to do anything, because the write which caused the
7686 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7687 which will do the appropriate cleanup for us. */
7690 x_connection_signal (signalnum
) /* If we don't have an argument, */
7691 int signalnum
; /* some compilers complain in signal calls. */
7694 /* USG systems forget handlers when they are used;
7695 must reestablish each time */
7696 signal (signalnum
, x_connection_signal
);
7701 /************************************************************************
7703 ************************************************************************/
7705 /* Error message passed to x_connection_closed. */
7707 static char *error_msg
;
7709 /* Function installed as fatal_error_signal_hook in
7710 x_connection_closed. Print the X error message, and exit normally,
7711 instead of dumping core when XtCloseDisplay fails. */
7714 x_fatal_error_signal ()
7716 fprintf (stderr
, "%s\n", error_msg
);
7720 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7721 the text of an error message that lead to the connection loss. */
7724 x_connection_closed (dpy
, error_message
)
7726 char *error_message
;
7728 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7729 Lisp_Object frame
, tail
;
7731 int index
= SPECPDL_INDEX ();
7733 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7734 strcpy (error_msg
, error_message
);
7735 handling_signal
= 0;
7737 /* Prevent being called recursively because of an error condition
7738 below. Otherwise, we might end up with printing ``can't find per
7739 display information'' in the recursive call instead of printing
7740 the original message here. */
7741 count
= x_catch_errors (dpy
);
7743 /* We have to close the display to inform Xt that it doesn't
7744 exist anymore. If we don't, Xt will continue to wait for
7745 events from the display. As a consequence, a sequence of
7747 M-x make-frame-on-display RET :1 RET
7748 ...kill the new frame, so that we get an IO error...
7749 M-x make-frame-on-display RET :1 RET
7751 will indefinitely wait in Xt for events for display `:1', opened
7752 in the first class to make-frame-on-display.
7754 Closing the display is reported to lead to a bus error on
7755 OpenWindows in certain situations. I suspect that is a bug
7756 in OpenWindows. I don't know how to cicumvent it here. */
7758 #ifdef USE_X_TOOLKIT
7759 /* If DPYINFO is null, this means we didn't open the display
7760 in the first place, so don't try to close it. */
7763 extern void (*fatal_error_signal_hook
) P_ ((void));
7764 fatal_error_signal_hook
= x_fatal_error_signal
;
7765 XtCloseDisplay (dpy
);
7766 fatal_error_signal_hook
= NULL
;
7772 xg_display_close (dpyinfo
->display
);
7775 /* Indicate that this display is dead. */
7777 dpyinfo
->display
= 0;
7779 /* Inhibit redisplay while frames are being deleted. */
7780 specbind (Qinhibit_redisplay
, Qt
);
7782 /* First delete frames whose mini-buffers are on frames
7783 that are on the dead display. */
7784 FOR_EACH_FRAME (tail
, frame
)
7786 Lisp_Object minibuf_frame
;
7788 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7789 if (FRAME_X_P (XFRAME (frame
))
7790 && FRAME_X_P (XFRAME (minibuf_frame
))
7791 && ! EQ (frame
, minibuf_frame
)
7792 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7793 Fdelete_frame (frame
, Qt
);
7796 /* Now delete all remaining frames on the dead display.
7797 We are now sure none of these is used as the mini-buffer
7798 for another frame that we need to delete. */
7799 FOR_EACH_FRAME (tail
, frame
)
7800 if (FRAME_X_P (XFRAME (frame
))
7801 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7803 /* Set this to t so that Fdelete_frame won't get confused
7804 trying to find a replacement. */
7805 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
7806 Fdelete_frame (frame
, Qt
);
7810 x_delete_display (dpyinfo
);
7812 x_uncatch_errors (dpy
, count
);
7814 if (display_list
== 0)
7816 fprintf (stderr
, "%s\n", error_msg
);
7817 shut_down_emacs (0, 0, Qnil
);
7821 /* Ordinary stack unwind doesn't deal with these. */
7823 sigunblock (sigmask (SIGIO
));
7825 sigunblock (sigmask (SIGALRM
));
7826 TOTALLY_UNBLOCK_INPUT
;
7828 unbind_to (index
, Qnil
);
7829 clear_waiting_for_input ();
7830 error ("%s", error_msg
);
7834 /* This is the usual handler for X protocol errors.
7835 It kills all frames on the display that we got the error for.
7836 If that was the only one, it prints an error message and kills Emacs. */
7839 x_error_quitter (display
, error
)
7843 char buf
[256], buf1
[356];
7845 /* Note that there is no real way portable across R3/R4 to get the
7846 original error handler. */
7848 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
7849 sprintf (buf1
, "X protocol error: %s on protocol request %d",
7850 buf
, error
->request_code
);
7851 x_connection_closed (display
, buf1
);
7855 /* This is the first-level handler for X protocol errors.
7856 It calls x_error_quitter or x_error_catcher. */
7859 x_error_handler (display
, error
)
7863 if (! NILP (x_error_message_string
))
7864 x_error_catcher (display
, error
);
7866 x_error_quitter (display
, error
);
7870 /* This is the handler for X IO errors, always.
7871 It kills all frames on the display that we lost touch with.
7872 If that was the only one, it prints an error message and kills Emacs. */
7875 x_io_error_quitter (display
)
7880 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
7881 x_connection_closed (display
, buf
);
7885 /* Changing the font of the frame. */
7887 /* Give frame F the font named FONTNAME as its default font, and
7888 return the full name of that font. FONTNAME may be a wildcard
7889 pattern; in that case, we choose some font that fits the pattern.
7890 The return value shows which font we chose. */
7893 x_new_font (f
, fontname
)
7895 register char *fontname
;
7897 struct font_info
*fontp
7898 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7903 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7904 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7905 FRAME_FONTSET (f
) = -1;
7907 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
7908 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
7910 compute_fringe_widths (f
, 1);
7912 /* Compute the scroll bar width in character columns. */
7913 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
7915 int wid
= FRAME_COLUMN_WIDTH (f
);
7916 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
7917 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
7921 int wid
= FRAME_COLUMN_WIDTH (f
);
7922 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
7925 /* Now make the frame display the given font. */
7926 if (FRAME_X_WINDOW (f
) != 0)
7928 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
7929 FRAME_FONT (f
)->fid
);
7930 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
7931 FRAME_FONT (f
)->fid
);
7932 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
7933 FRAME_FONT (f
)->fid
);
7935 /* Don't change the size of a tip frame; there's no point in
7936 doing it because it's done in Fx_show_tip, and it leads to
7937 problems because the tip frame has no widget. */
7938 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7939 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
7942 return build_string (fontp
->full_name
);
7945 /* Give frame F the fontset named FONTSETNAME as its default font, and
7946 return the full name of that fontset. FONTSETNAME may be a wildcard
7947 pattern; in that case, we choose some fontset that fits the pattern.
7948 The return value shows which fontset we chose. */
7951 x_new_fontset (f
, fontsetname
)
7955 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
7961 if (FRAME_FONTSET (f
) == fontset
)
7962 /* This fontset is already set in frame F. There's nothing more
7964 return fontset_name (fontset
);
7966 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
7968 if (!STRINGP (result
))
7969 /* Can't load ASCII font. */
7972 /* Since x_new_font doesn't update any fontset information, do it now. */
7973 FRAME_FONTSET (f
) = fontset
;
7977 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
7978 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
7981 return build_string (fontsetname
);
7985 /***********************************************************************
7987 ***********************************************************************/
7993 /* XIM destroy callback function, which is called whenever the
7994 connection to input method XIM dies. CLIENT_DATA contains a
7995 pointer to the x_display_info structure corresponding to XIM. */
7998 xim_destroy_callback (xim
, client_data
, call_data
)
8000 XPointer client_data
;
8003 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
8004 Lisp_Object frame
, tail
;
8008 /* No need to call XDestroyIC.. */
8009 FOR_EACH_FRAME (tail
, frame
)
8011 struct frame
*f
= XFRAME (frame
);
8012 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
8014 FRAME_XIC (f
) = NULL
;
8015 if (FRAME_XIC_FONTSET (f
))
8017 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
8018 FRAME_XIC_FONTSET (f
) = NULL
;
8023 /* No need to call XCloseIM. */
8024 dpyinfo
->xim
= NULL
;
8025 XFree (dpyinfo
->xim_styles
);
8029 #endif /* HAVE_X11R6 */
8032 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8033 extern char *XSetIMValues
P_ ((XIM
, ...));
8036 /* Open the connection to the XIM server on display DPYINFO.
8037 RESOURCE_NAME is the resource name Emacs uses. */
8040 xim_open_dpy (dpyinfo
, resource_name
)
8041 struct x_display_info
*dpyinfo
;
8042 char *resource_name
;
8049 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
8056 XIMCallback destroy
;
8059 /* Get supported styles and XIM values. */
8060 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
8063 destroy
.callback
= xim_destroy_callback
;
8064 destroy
.client_data
= (XPointer
)dpyinfo
;
8065 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8071 #endif /* HAVE_XIM */
8072 dpyinfo
->xim
= NULL
;
8076 #ifdef HAVE_X11R6_XIM
8080 struct x_display_info
*dpyinfo
;
8081 char *resource_name
;
8084 /* XIM instantiate callback function, which is called whenever an XIM
8085 server is available. DISPLAY is the display of the XIM.
8086 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8087 when the callback was registered. */
8090 xim_instantiate_callback (display
, client_data
, call_data
)
8092 XPointer client_data
;
8095 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8096 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8098 /* We don't support multiple XIM connections. */
8102 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8104 /* Create XIC for the existing frames on the same display, as long
8105 as they have no XIC. */
8106 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8108 Lisp_Object tail
, frame
;
8111 FOR_EACH_FRAME (tail
, frame
)
8113 struct frame
*f
= XFRAME (frame
);
8116 && FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8117 if (FRAME_XIC (f
) == NULL
)
8119 create_frame_xic (f
);
8120 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8121 xic_set_statusarea (f
);
8122 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8124 struct window
*w
= XWINDOW (f
->selected_window
);
8125 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8134 #endif /* HAVE_X11R6_XIM */
8137 /* Open a connection to the XIM server on display DPYINFO.
8138 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8139 connection only at the first time. On X11R6, open the connection
8140 in the XIM instantiate callback function. */
8143 xim_initialize (dpyinfo
, resource_name
)
8144 struct x_display_info
*dpyinfo
;
8145 char *resource_name
;
8150 #ifdef HAVE_X11R6_XIM
8151 struct xim_inst_t
*xim_inst
;
8154 dpyinfo
->xim
= NULL
;
8155 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8156 xim_inst
->dpyinfo
= dpyinfo
;
8157 len
= strlen (resource_name
);
8158 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8159 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
8160 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8161 resource_name
, EMACS_CLASS
,
8162 xim_instantiate_callback
,
8163 /* This is XPointer in XFree86
8164 but (XPointer *) on Tru64, at
8165 least, hence the configure test. */
8166 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8167 #else /* not HAVE_X11R6_XIM */
8168 dpyinfo
->xim
= NULL
;
8169 xim_open_dpy (dpyinfo
, resource_name
);
8170 #endif /* not HAVE_X11R6_XIM */
8174 #endif /* HAVE_XIM */
8175 dpyinfo
->xim
= NULL
;
8179 /* Close the connection to the XIM server on display DPYINFO. */
8182 xim_close_dpy (dpyinfo
)
8183 struct x_display_info
*dpyinfo
;
8188 #ifdef HAVE_X11R6_XIM
8189 if (dpyinfo
->display
)
8190 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8192 xim_instantiate_callback
, NULL
);
8193 #endif /* not HAVE_X11R6_XIM */
8194 if (dpyinfo
->display
)
8195 XCloseIM (dpyinfo
->xim
);
8196 dpyinfo
->xim
= NULL
;
8197 XFree (dpyinfo
->xim_styles
);
8199 #endif /* HAVE_XIM */
8202 #endif /* not HAVE_X11R6_XIM */
8206 /* Calculate the absolute position in frame F
8207 from its current recorded position values and gravity. */
8210 x_calc_absolute_position (f
)
8213 int win_x
= 0, win_y
= 0;
8214 int flags
= f
->size_hint_flags
;
8216 /* We have nothing to do if the current position
8217 is already for the top-left corner. */
8218 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8221 /* Find the offsets of the outside upper-left corner of
8222 the inner window, with respect to the outer window.
8223 But do this only if we will need the results. */
8224 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
8225 /* This is to get *_pixels_outer_diff. */
8226 x_real_positions (f
, &win_x
, &win_y
);
8228 /* Treat negative positions as relative to the leftmost bottommost
8229 position that fits on the screen. */
8230 if (flags
& XNegative
)
8231 f
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
8232 - 2 * FRAME_X_OUTPUT (f
)->x_pixels_outer_diff
8233 - FRAME_PIXEL_WIDTH (f
)
8237 int height
= FRAME_PIXEL_HEIGHT (f
);
8239 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8240 /* Something is fishy here. When using Motif, starting Emacs with
8241 `-g -0-0', the frame appears too low by a few pixels.
8243 This seems to be so because initially, while Emacs is starting,
8244 the column widget's height and the frame's pixel height are
8245 different. The column widget's height is the right one. In
8246 later invocations, when Emacs is up, the frame's pixel height
8249 It's not obvious where the initial small difference comes from.
8250 2000-12-01, gerd. */
8252 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8255 if (flags
& YNegative
)
8256 f
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
8257 - FRAME_X_OUTPUT (f
)->y_pixels_outer_diff
8259 /* Assume the window manager decorations are the same size on
8260 three sides, i.e. left, right and bottom. This is to
8261 compensate for the bottom part. */
8262 - FRAME_X_OUTPUT (f
)->x_pixels_outer_diff
8267 /* The left_pos and top_pos
8268 are now relative to the top and left screen edges,
8269 so the flags should correspond. */
8270 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8273 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8274 to really change the position, and 0 when calling from
8275 x_make_frame_visible (in that case, XOFF and YOFF are the current
8276 position values). It is -1 when calling from x_set_frame_parameters,
8277 which means, do adjust for borders but don't change the gravity. */
8280 x_set_offset (f
, xoff
, yoff
, change_gravity
)
8282 register int xoff
, yoff
;
8285 int modified_top
, modified_left
;
8287 if (change_gravity
> 0)
8291 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8293 f
->size_hint_flags
|= XNegative
;
8295 f
->size_hint_flags
|= YNegative
;
8296 f
->win_gravity
= NorthWestGravity
;
8298 x_calc_absolute_position (f
);
8301 x_wm_set_size_hint (f
, (long) 0, 0);
8303 modified_left
= f
->left_pos
;
8304 modified_top
= f
->top_pos
;
8306 if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8308 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8309 than the WM decorations. So we use the calculated offset instead
8310 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8311 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8312 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8315 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8316 modified_left
, modified_top
);
8318 if (FRAME_VISIBLE_P (f
)
8319 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8321 FRAME_X_OUTPUT (f
)->check_expected_move
= 1;
8322 FRAME_X_OUTPUT (f
)->expected_top
= f
->top_pos
;
8323 FRAME_X_OUTPUT (f
)->expected_left
= f
->left_pos
;
8329 /* Check if we need to resize the frame due to a fullscreen request.
8330 If so needed, resize the frame. */
8332 x_check_fullscreen (f
)
8335 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
8337 int width
, height
, ign
;
8339 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8341 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
8343 /* We do not need to move the window, it shall be taken care of
8344 when setting WM manager hints.
8345 If the frame is visible already, the position is checked by
8346 x_check_expected_move. */
8347 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
8349 change_frame_size (f
, height
, width
, 0, 1, 0);
8350 SET_FRAME_GARBAGED (f
);
8351 cancel_mouse_face (f
);
8353 /* Wait for the change of frame size to occur */
8354 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
8359 /* If frame parameters are set after the frame is mapped, we need to move
8361 Some window managers moves the window to the right position, some
8362 moves the outer window manager window to the specified position.
8363 Here we check that we are in the right spot. If not, make a second
8364 move, assuming we are dealing with the second kind of window manager. */
8366 x_check_expected_move (f
)
8369 if (FRAME_X_OUTPUT (f
)->check_expected_move
)
8371 int expect_top
= FRAME_X_OUTPUT (f
)->expected_top
;
8372 int expect_left
= FRAME_X_OUTPUT (f
)->expected_left
;
8374 if (expect_top
!= f
->top_pos
|| expect_left
!= f
->left_pos
)
8376 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8377 FRAME_X_OUTPUT (f
)->move_offset_left
= expect_left
- f
->left_pos
;
8378 FRAME_X_OUTPUT (f
)->move_offset_top
= expect_top
- f
->top_pos
;
8380 x_set_offset (f
, expect_left
, expect_top
, 1);
8382 else if (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
)
8383 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8385 /* Just do this once */
8386 FRAME_X_OUTPUT (f
)->check_expected_move
= 0;
8391 /* Change the size of frame F's X window to COLS/ROWS in the case F
8392 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8393 top-left-corner window gravity for this size change and subsequent
8394 size changes. Otherwise we leave the window gravity unchanged. */
8397 x_set_window_size_1 (f
, change_gravity
, cols
, rows
)
8402 int pixelwidth
, pixelheight
;
8404 check_frame_size (f
, &rows
, &cols
);
8405 f
->scroll_bar_actual_width
8406 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8408 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0
8409 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f
)
8410 : (FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
)));
8412 compute_fringe_widths (f
, 0);
8414 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
8415 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8417 f
->win_gravity
= NorthWestGravity
;
8418 x_wm_set_size_hint (f
, (long) 0, 0);
8420 XSync (FRAME_X_DISPLAY (f
), False
);
8421 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8422 pixelwidth
, pixelheight
);
8424 /* Now, strictly speaking, we can't be sure that this is accurate,
8425 but the window manager will get around to dealing with the size
8426 change request eventually, and we'll hear how it went when the
8427 ConfigureNotify event gets here.
8429 We could just not bother storing any of this information here,
8430 and let the ConfigureNotify event set everything up, but that
8431 might be kind of confusing to the Lisp code, since size changes
8432 wouldn't be reported in the frame parameters until some random
8433 point in the future when the ConfigureNotify event arrives.
8435 We pass 1 for DELAY since we can't run Lisp code inside of
8437 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8438 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8439 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8441 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8442 receive in the ConfigureNotify event; if we get what we asked
8443 for, then the event won't cause the screen to become garbaged, so
8444 we have to make sure to do it here. */
8445 SET_FRAME_GARBAGED (f
);
8447 XFlush (FRAME_X_DISPLAY (f
));
8451 /* Call this to change the size of frame F's x-window.
8452 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8453 for this size change and subsequent size changes.
8454 Otherwise we leave the window gravity unchanged. */
8457 x_set_window_size (f
, change_gravity
, cols
, rows
)
8465 if (FRAME_GTK_WIDGET (f
))
8466 xg_frame_set_char_size (f
, cols
, rows
);
8468 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8471 if (f
->output_data
.x
->widget
!= NULL
)
8473 /* The x and y position of the widget is clobbered by the
8474 call to XtSetValues within EmacsFrameSetCharSize.
8475 This is a real kludge, but I don't understand Xt so I can't
8476 figure out a correct fix. Can anyone else tell me? -- rms. */
8477 int xpos
= f
->output_data
.x
->widget
->core
.x
;
8478 int ypos
= f
->output_data
.x
->widget
->core
.y
;
8479 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
8480 f
->output_data
.x
->widget
->core
.x
= xpos
;
8481 f
->output_data
.x
->widget
->core
.y
= ypos
;
8484 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8486 #else /* not USE_X_TOOLKIT */
8488 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8490 #endif /* not USE_X_TOOLKIT */
8492 /* If cursor was outside the new size, mark it as off. */
8493 mark_window_cursors_off (XWINDOW (f
->root_window
));
8495 /* Clear out any recollection of where the mouse highlighting was,
8496 since it might be in a place that's outside the new frame size.
8497 Actually checking whether it is outside is a pain in the neck,
8498 so don't try--just let the highlighting be done afresh with new size. */
8499 cancel_mouse_face (f
);
8504 /* Mouse warping. */
8507 x_set_mouse_position (f
, x
, y
)
8513 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
8514 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
8516 if (pix_x
< 0) pix_x
= 0;
8517 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
8519 if (pix_y
< 0) pix_y
= 0;
8520 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
8524 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8525 0, 0, 0, 0, pix_x
, pix_y
);
8529 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8532 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
8538 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8539 0, 0, 0, 0, pix_x
, pix_y
);
8543 /* focus shifting, raising and lowering. */
8546 x_focus_on_frame (f
)
8549 #if 0 /* This proves to be unpleasant. */
8553 /* I don't think that the ICCCM allows programs to do things like this
8554 without the interaction of the window manager. Whatever you end up
8555 doing with this code, do it to x_unfocus_frame too. */
8556 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8557 RevertToPointerRoot
, CurrentTime
);
8566 /* Look at the remarks in x_focus_on_frame. */
8567 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
8568 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
8569 RevertToPointerRoot
, CurrentTime
);
8573 /* Raise frame F. */
8579 if (f
->async_visible
)
8582 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8583 XFlush (FRAME_X_DISPLAY (f
));
8588 /* Lower frame F. */
8594 if (f
->async_visible
)
8597 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8598 XFlush (FRAME_X_DISPLAY (f
));
8604 XTframe_raise_lower (f
, raise_flag
)
8614 /* Change of visibility. */
8616 /* This tries to wait until the frame is really visible.
8617 However, if the window manager asks the user where to position
8618 the frame, this will return before the user finishes doing that.
8619 The frame will not actually be visible at that time,
8620 but it will become visible later when the window manager
8621 finishes with it. */
8624 x_make_frame_visible (f
)
8628 int original_top
, original_left
;
8629 int retry_count
= 2;
8635 type
= x_icon_type (f
);
8637 x_bitmap_icon (f
, type
);
8639 if (! FRAME_VISIBLE_P (f
))
8641 /* We test FRAME_GARBAGED_P here to make sure we don't
8642 call x_set_offset a second time
8643 if we get to x_make_frame_visible a second time
8644 before the window gets really visible. */
8645 if (! FRAME_ICONIFIED_P (f
)
8646 && ! f
->output_data
.x
->asked_for_visible
)
8647 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8649 f
->output_data
.x
->asked_for_visible
= 1;
8651 if (! EQ (Vx_no_window_manager
, Qt
))
8652 x_wm_set_window_state (f
, NormalState
);
8653 #ifdef USE_X_TOOLKIT
8654 /* This was XtPopup, but that did nothing for an iconified frame. */
8655 XtMapWidget (f
->output_data
.x
->widget
);
8656 #else /* not USE_X_TOOLKIT */
8658 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8659 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8661 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8662 #endif /* not USE_GTK */
8663 #endif /* not USE_X_TOOLKIT */
8664 #if 0 /* This seems to bring back scroll bars in the wrong places
8665 if the window configuration has changed. They seem
8666 to come back ok without this. */
8667 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8668 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8672 XFlush (FRAME_X_DISPLAY (f
));
8674 /* Synchronize to ensure Emacs knows the frame is visible
8675 before we do anything else. We do this loop with input not blocked
8676 so that incoming events are handled. */
8680 /* This must be before UNBLOCK_INPUT
8681 since events that arrive in response to the actions above
8682 will set it when they are handled. */
8683 int previously_visible
= f
->output_data
.x
->has_been_visible
;
8685 original_left
= f
->left_pos
;
8686 original_top
= f
->top_pos
;
8688 /* This must come after we set COUNT. */
8691 /* We unblock here so that arriving X events are processed. */
8693 /* Now move the window back to where it was "supposed to be".
8694 But don't do it if the gravity is negative.
8695 When the gravity is negative, this uses a position
8696 that is 3 pixels too low. Perhaps that's really the border width.
8698 Don't do this if the window has never been visible before,
8699 because the window manager may choose the position
8700 and we don't want to override it. */
8702 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
8703 && f
->win_gravity
== NorthWestGravity
8704 && previously_visible
)
8708 unsigned int width
, height
, border
, depth
;
8712 /* On some window managers (such as FVWM) moving an existing
8713 window, even to the same place, causes the window manager
8714 to introduce an offset. This can cause the window to move
8715 to an unexpected location. Check the geometry (a little
8716 slow here) and then verify that the window is in the right
8717 place. If the window is not in the right place, move it
8718 there, and take the potential window manager hit. */
8719 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8720 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
8722 if (original_left
!= x
|| original_top
!= y
)
8723 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8724 original_left
, original_top
);
8729 XSETFRAME (frame
, f
);
8731 /* Wait until the frame is visible. Process X events until a
8732 MapNotify event has been seen, or until we think we won't get a
8733 MapNotify at all.. */
8734 for (count
= input_signal_count
+ 10;
8735 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
8737 /* Force processing of queued events. */
8740 /* Machines that do polling rather than SIGIO have been
8741 observed to go into a busy-wait here. So we'll fake an
8742 alarm signal to let the handler know that there's something
8743 to be read. We used to raise a real alarm, but it seems
8744 that the handler isn't always enabled here. This is
8746 if (input_polling_used ())
8748 /* It could be confusing if a real alarm arrives while
8749 processing the fake one. Turn it off and let the
8750 handler reset it. */
8751 extern void poll_for_input_1
P_ ((void));
8752 int old_poll_suppress_count
= poll_suppress_count
;
8753 poll_suppress_count
= 1;
8754 poll_for_input_1 ();
8755 poll_suppress_count
= old_poll_suppress_count
;
8758 /* See if a MapNotify event has been processed. */
8759 FRAME_SAMPLE_VISIBILITY (f
);
8764 (let ((f (selected-frame)))
8768 the frame is not raised with various window managers on
8769 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
8770 unknown reason, the call to XtMapWidget is completely ignored.
8771 Mapping the widget a second time works. */
8773 if (!FRAME_VISIBLE_P (f
) && --retry_count
> 0)
8778 /* Change from mapped state to withdrawn state. */
8780 /* Make the frame visible (mapped and not iconified). */
8783 x_make_frame_invisible (f
)
8788 /* Use the frame's outermost window, not the one we normally draw on. */
8789 window
= FRAME_OUTER_WINDOW (f
);
8791 /* Don't keep the highlight on an invisible frame. */
8792 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8793 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8795 #if 0/* This might add unreliability; I don't trust it -- rms. */
8796 if (! f
->async_visible
&& ! f
->async_iconified
)
8802 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
8803 that the current position of the window is user-specified, rather than
8804 program-specified, so that when the window is mapped again, it will be
8805 placed at the same location, without forcing the user to position it
8806 by hand again (they have already done that once for this window.) */
8807 x_wm_set_size_hint (f
, (long) 0, 1);
8810 if (FRAME_GTK_OUTER_WIDGET (f
))
8811 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
8817 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
8818 DefaultScreen (FRAME_X_DISPLAY (f
))))
8820 UNBLOCK_INPUT_RESIGNAL
;
8821 error ("Can't notify window manager of window withdrawal");
8823 #else /* ! defined (HAVE_X11R4) */
8825 /* Tell the window manager what we're going to do. */
8826 if (! EQ (Vx_no_window_manager
, Qt
))
8830 unmap
.xunmap
.type
= UnmapNotify
;
8831 unmap
.xunmap
.window
= window
;
8832 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
8833 unmap
.xunmap
.from_configure
= False
;
8834 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8835 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8837 SubstructureRedirectMaskSubstructureNotifyMask
,
8840 UNBLOCK_INPUT_RESIGNAL
;
8841 error ("Can't notify window manager of withdrawal");
8845 /* Unmap the window ourselves. Cheeky! */
8846 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
8847 #endif /* ! defined (HAVE_X11R4) */
8850 /* We can't distinguish this from iconification
8851 just by the event that we get from the server.
8852 So we can't win using the usual strategy of letting
8853 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8854 and synchronize with the server to make sure we agree. */
8856 FRAME_ICONIFIED_P (f
) = 0;
8857 f
->async_visible
= 0;
8858 f
->async_iconified
= 0;
8865 /* Change window state from mapped to iconified. */
8874 /* Don't keep the highlight on an invisible frame. */
8875 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8876 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8878 if (f
->async_iconified
)
8883 FRAME_SAMPLE_VISIBILITY (f
);
8885 type
= x_icon_type (f
);
8887 x_bitmap_icon (f
, type
);
8890 if (FRAME_GTK_OUTER_WIDGET (f
))
8892 if (! FRAME_VISIBLE_P (f
))
8893 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8895 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8898 f
->async_iconified
= 1;
8899 f
->async_visible
= 0;
8905 #ifdef USE_X_TOOLKIT
8907 if (! FRAME_VISIBLE_P (f
))
8909 if (! EQ (Vx_no_window_manager
, Qt
))
8910 x_wm_set_window_state (f
, IconicState
);
8911 /* This was XtPopup, but that did nothing for an iconified frame. */
8912 XtMapWidget (f
->output_data
.x
->widget
);
8913 /* The server won't give us any event to indicate
8914 that an invisible frame was changed to an icon,
8915 so we have to record it here. */
8918 f
->async_iconified
= 1;
8919 f
->async_visible
= 0;
8924 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
8925 XtWindow (f
->output_data
.x
->widget
),
8926 DefaultScreen (FRAME_X_DISPLAY (f
)));
8930 error ("Can't notify window manager of iconification");
8932 f
->async_iconified
= 1;
8933 f
->async_visible
= 0;
8937 XFlush (FRAME_X_DISPLAY (f
));
8939 #else /* not USE_X_TOOLKIT */
8941 /* Make sure the X server knows where the window should be positioned,
8942 in case the user deiconifies with the window manager. */
8943 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
8944 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8946 /* Since we don't know which revision of X we're running, we'll use both
8947 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
8949 /* X11R4: send a ClientMessage to the window manager using the
8950 WM_CHANGE_STATE type. */
8954 message
.xclient
.window
= FRAME_X_WINDOW (f
);
8955 message
.xclient
.type
= ClientMessage
;
8956 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
8957 message
.xclient
.format
= 32;
8958 message
.xclient
.data
.l
[0] = IconicState
;
8960 if (! XSendEvent (FRAME_X_DISPLAY (f
),
8961 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
8963 SubstructureRedirectMask
| SubstructureNotifyMask
,
8966 UNBLOCK_INPUT_RESIGNAL
;
8967 error ("Can't notify window manager of iconification");
8971 /* X11R3: set the initial_state field of the window manager hints to
8973 x_wm_set_window_state (f
, IconicState
);
8975 if (!FRAME_VISIBLE_P (f
))
8977 /* If the frame was withdrawn, before, we must map it. */
8978 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8981 f
->async_iconified
= 1;
8982 f
->async_visible
= 0;
8984 XFlush (FRAME_X_DISPLAY (f
));
8986 #endif /* not USE_X_TOOLKIT */
8990 /* Free X resources of frame F. */
8993 x_free_frame_resources (f
)
8996 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8998 struct scroll_bar
*b
;
9002 /* If a display connection is dead, don't try sending more
9003 commands to the X server. */
9004 if (dpyinfo
->display
)
9006 if (f
->output_data
.x
->icon_desc
)
9007 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
9009 #ifdef USE_X_TOOLKIT
9010 /* Explicitly destroy the scroll bars of the frame. Without
9011 this, we get "BadDrawable" errors from the toolkit later on,
9012 presumably from expose events generated for the disappearing
9013 toolkit scroll bars. */
9014 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
9016 b
= XSCROLL_BAR (bar
);
9017 x_scroll_bar_remove (b
);
9026 #ifdef USE_X_TOOLKIT
9027 if (f
->output_data
.x
->widget
)
9029 XtDestroyWidget (f
->output_data
.x
->widget
);
9030 f
->output_data
.x
->widget
= NULL
;
9032 /* Tooltips don't have widgets, only a simple X window, even if
9033 we are using a toolkit. */
9034 else if (FRAME_X_WINDOW (f
))
9035 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9037 free_frame_menubar (f
);
9038 #else /* !USE_X_TOOLKIT */
9041 /* In the GTK version, tooltips are normal X
9042 frames. We must check and free both types. */
9043 if (FRAME_GTK_OUTER_WIDGET (f
))
9045 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f
));
9046 FRAME_X_WINDOW (f
) = 0; /* Set to avoid XDestroyWindow below */
9047 FRAME_GTK_OUTER_WIDGET (f
) = 0;
9049 #endif /* USE_GTK */
9051 if (FRAME_X_WINDOW (f
))
9052 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9053 #endif /* !USE_X_TOOLKIT */
9055 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
9056 unload_color (f
, f
->output_data
.x
->background_pixel
);
9057 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9058 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9059 unload_color (f
, f
->output_data
.x
->border_pixel
);
9060 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9062 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9063 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9064 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9065 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9066 #ifdef USE_TOOLKIT_SCROLL_BARS
9067 /* Scrollbar shadow colors. */
9068 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9069 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9070 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9071 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9072 #endif /* USE_TOOLKIT_SCROLL_BARS */
9073 if (f
->output_data
.x
->white_relief
.allocated_p
)
9074 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9075 if (f
->output_data
.x
->black_relief
.allocated_p
)
9076 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9078 if (FRAME_FACE_CACHE (f
))
9079 free_frame_faces (f
);
9082 XFlush (FRAME_X_DISPLAY (f
));
9085 if (f
->output_data
.x
->saved_menu_event
)
9086 xfree (f
->output_data
.x
->saved_menu_event
);
9088 xfree (f
->output_data
.x
);
9089 f
->output_data
.x
= NULL
;
9091 if (f
== dpyinfo
->x_focus_frame
)
9092 dpyinfo
->x_focus_frame
= 0;
9093 if (f
== dpyinfo
->x_focus_event_frame
)
9094 dpyinfo
->x_focus_event_frame
= 0;
9095 if (f
== dpyinfo
->x_highlight_frame
)
9096 dpyinfo
->x_highlight_frame
= 0;
9098 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9100 dpyinfo
->mouse_face_beg_row
9101 = dpyinfo
->mouse_face_beg_col
= -1;
9102 dpyinfo
->mouse_face_end_row
9103 = dpyinfo
->mouse_face_end_col
= -1;
9104 dpyinfo
->mouse_face_window
= Qnil
;
9105 dpyinfo
->mouse_face_deferred_gc
= 0;
9106 dpyinfo
->mouse_face_mouse_frame
= 0;
9113 /* Destroy the X window of frame F. */
9116 x_destroy_window (f
)
9119 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9121 /* If a display connection is dead, don't try sending more
9122 commands to the X server. */
9123 if (dpyinfo
->display
!= 0)
9124 x_free_frame_resources (f
);
9126 dpyinfo
->reference_count
--;
9130 /* Setting window manager hints. */
9132 /* Set the normal size hints for the window manager, for frame F.
9133 FLAGS is the flags word to use--or 0 meaning preserve the flags
9134 that the window now has.
9135 If USER_POSITION is nonzero, we set the USPosition
9136 flag (this is useful when FLAGS is 0).
9137 The GTK version is in gtkutils.c */
9141 x_wm_set_size_hint (f
, flags
, user_position
)
9146 XSizeHints size_hints
;
9148 #ifdef USE_X_TOOLKIT
9151 Dimension widget_width
, widget_height
;
9154 Window window
= FRAME_OUTER_WINDOW (f
);
9156 /* Setting PMaxSize caused various problems. */
9157 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9159 size_hints
.x
= f
->left_pos
;
9160 size_hints
.y
= f
->top_pos
;
9162 #ifdef USE_X_TOOLKIT
9163 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
9164 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
9165 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
9166 size_hints
.height
= widget_height
;
9167 size_hints
.width
= widget_width
;
9168 #else /* not USE_X_TOOLKIT */
9169 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9170 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9171 #endif /* not USE_X_TOOLKIT */
9173 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9174 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9175 size_hints
.max_width
9176 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9177 size_hints
.max_height
9178 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9180 /* Calculate the base and minimum sizes.
9182 (When we use the X toolkit, we don't do it here.
9183 Instead we copy the values that the widgets are using, below.) */
9184 #ifndef USE_X_TOOLKIT
9186 int base_width
, base_height
;
9187 int min_rows
= 0, min_cols
= 0;
9189 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9190 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9192 check_frame_size (f
, &min_rows
, &min_cols
);
9194 /* The window manager uses the base width hints to calculate the
9195 current number of rows and columns in the frame while
9196 resizing; min_width and min_height aren't useful for this
9197 purpose, since they might not give the dimensions for a
9198 zero-row, zero-column frame.
9200 We use the base_width and base_height members if we have
9201 them; otherwise, we set the min_width and min_height members
9202 to the size for a zero x zero frame. */
9205 size_hints
.flags
|= PBaseSize
;
9206 size_hints
.base_width
= base_width
;
9207 size_hints
.base_height
= base_height
;
9208 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9209 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9211 size_hints
.min_width
= base_width
;
9212 size_hints
.min_height
= base_height
;
9216 /* If we don't need the old flags, we don't need the old hint at all. */
9219 size_hints
.flags
|= flags
;
9222 #endif /* not USE_X_TOOLKIT */
9225 XSizeHints hints
; /* Sometimes I hate X Windows... */
9226 long supplied_return
;
9230 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9233 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
9236 #ifdef USE_X_TOOLKIT
9237 size_hints
.base_height
= hints
.base_height
;
9238 size_hints
.base_width
= hints
.base_width
;
9239 size_hints
.min_height
= hints
.min_height
;
9240 size_hints
.min_width
= hints
.min_width
;
9244 size_hints
.flags
|= flags
;
9249 if (hints
.flags
& PSize
)
9250 size_hints
.flags
|= PSize
;
9251 if (hints
.flags
& PPosition
)
9252 size_hints
.flags
|= PPosition
;
9253 if (hints
.flags
& USPosition
)
9254 size_hints
.flags
|= USPosition
;
9255 if (hints
.flags
& USSize
)
9256 size_hints
.flags
|= USSize
;
9260 #ifndef USE_X_TOOLKIT
9265 size_hints
.win_gravity
= f
->win_gravity
;
9266 size_hints
.flags
|= PWinGravity
;
9270 size_hints
.flags
&= ~ PPosition
;
9271 size_hints
.flags
|= USPosition
;
9273 #endif /* PWinGravity */
9276 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9278 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9281 #endif /* not USE_GTK */
9283 /* Used for IconicState or NormalState */
9286 x_wm_set_window_state (f
, state
)
9290 #ifdef USE_X_TOOLKIT
9293 XtSetArg (al
[0], XtNinitialState
, state
);
9294 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9295 #else /* not USE_X_TOOLKIT */
9296 Window window
= FRAME_X_WINDOW (f
);
9298 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9299 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9301 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9302 #endif /* not USE_X_TOOLKIT */
9306 x_wm_set_icon_pixmap (f
, pixmap_id
)
9310 Pixmap icon_pixmap
, icon_mask
;
9312 #ifndef USE_X_TOOLKIT
9313 Window window
= FRAME_OUTER_WINDOW (f
);
9318 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9319 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9320 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9321 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9325 /* It seems there is no way to turn off use of an icon pixmap.
9326 The following line does it, only if no icon has yet been created,
9327 for some window managers. But with mwm it crashes.
9328 Some people say it should clear the IconPixmapHint bit in this case,
9329 but that doesn't work, and the X consortium said it isn't the
9330 right thing at all. Since there is no way to win,
9331 best to explicitly give up. */
9333 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
9334 f
->output_data
.x
->wm_hints
.icon_mask
= None
;
9340 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
9344 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9345 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9346 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9347 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9350 #else /* not USE_X_TOOLKIT */
9352 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9353 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9355 #endif /* not USE_X_TOOLKIT */
9359 x_wm_set_icon_position (f
, icon_x
, icon_y
)
9363 Window window
= FRAME_OUTER_WINDOW (f
);
9365 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9366 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9367 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9369 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9373 /***********************************************************************
9375 ***********************************************************************/
9377 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9380 x_get_font_info (f
, font_idx
)
9384 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
9388 /* Return a list of names of available fonts matching PATTERN on frame F.
9390 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9393 SIZE < 0 means include scalable fonts.
9395 Frame F null means we have not yet created any frame on X, and
9396 consult the first display in x_display_list. MAXNAMES sets a limit
9397 on how many fonts to match. */
9400 x_list_fonts (f
, pattern
, size
, maxnames
)
9402 Lisp_Object pattern
;
9406 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
9407 Lisp_Object tem
, second_best
;
9408 struct x_display_info
*dpyinfo
9409 = f
? FRAME_X_DISPLAY_INFO (f
) : x_display_list
;
9410 Display
*dpy
= dpyinfo
->display
;
9411 int try_XLoadQueryFont
= 0;
9413 int allow_auto_scaled_font
= 0;
9417 allow_auto_scaled_font
= 1;
9421 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
9422 if (NILP (patterns
))
9423 patterns
= Fcons (pattern
, Qnil
);
9425 if (maxnames
== 1 && !size
)
9426 /* We can return any single font matching PATTERN. */
9427 try_XLoadQueryFont
= 1;
9429 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
9432 char **names
= NULL
;
9434 pattern
= XCAR (patterns
);
9435 /* See if we cached the result for this particular query.
9436 The cache is an alist of the form:
9437 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
9438 tem
= XCDR (dpyinfo
->name_list_element
);
9439 key
= Fcons (Fcons (pattern
, make_number (maxnames
)),
9440 allow_auto_scaled_font
? Qt
: Qnil
);
9441 list
= Fassoc (key
, tem
);
9444 list
= Fcdr_safe (list
);
9445 /* We have a cashed list. Don't have to get the list again. */
9449 /* At first, put PATTERN in the cache. */
9452 count
= x_catch_errors (dpy
);
9454 if (try_XLoadQueryFont
)
9457 unsigned long value
;
9459 font
= XLoadQueryFont (dpy
, SDATA (pattern
));
9460 if (x_had_errors_p (dpy
))
9462 /* This error is perhaps due to insufficient memory on X
9463 server. Let's just ignore it. */
9465 x_clear_errors (dpy
);
9469 && XGetFontProperty (font
, XA_FONT
, &value
))
9471 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
9472 int len
= strlen (name
);
9475 /* If DXPC (a Differential X Protocol Compressor)
9476 Ver.3.7 is running, XGetAtomName will return null
9477 string. We must avoid such a name. */
9479 try_XLoadQueryFont
= 0;
9483 names
= (char **) alloca (sizeof (char *));
9484 /* Some systems only allow alloca assigned to a
9486 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
9487 bcopy (name
, names
[0], len
+ 1);
9492 try_XLoadQueryFont
= 0;
9495 XFreeFont (dpy
, font
);
9498 if (!try_XLoadQueryFont
)
9500 /* We try at least 10 fonts because XListFonts will return
9501 auto-scaled fonts at the head. */
9508 names
= XListFonts (dpy
, SDATA (pattern
), limit
, &num_fonts
);
9509 if (num_fonts
== limit
)
9512 XFreeFontNames (names
);
9521 names
= XListFonts (dpy
, SDATA (pattern
), max (maxnames
, 10),
9524 if (x_had_errors_p (dpy
))
9526 /* This error is perhaps due to insufficient memory on X
9527 server. Let's just ignore it. */
9529 x_clear_errors (dpy
);
9533 x_uncatch_errors (dpy
, count
);
9540 /* Make a list of all the fonts we got back.
9541 Store that in the font cache for the display. */
9542 for (i
= 0; i
< num_fonts
; i
++)
9546 int average_width
= -1, resx
= 0, dashes
= 0;
9548 /* Count the number of dashes in NAMES[I]. If there are
9549 14 dashes, the field value following 9th dash
9550 (RESOLUTION_X) is nonzero, and the field value
9551 following 12th dash (AVERAGE_WIDTH) is 0, this is a
9552 auto-scaled font which is usually too ugly to be used
9553 for editing. Let's ignore it. */
9558 if (dashes
== 7) /* PIXEL_SIZE field */
9560 else if (dashes
== 9)
9562 else if (dashes
== 12) /* AVERAGE_WIDTH field */
9563 average_width
= atoi (p
);
9566 if (allow_auto_scaled_font
9567 || dashes
< 14 || average_width
!= 0 || resx
== 0)
9569 tem
= build_string (names
[i
]);
9570 if (NILP (Fassoc (tem
, list
)))
9572 if (STRINGP (Vx_pixel_size_width_font_regexp
)
9573 && ((fast_c_string_match_ignore_case
9574 (Vx_pixel_size_width_font_regexp
, names
[i
]))
9576 /* We can set the value of PIXEL_SIZE to the
9577 width of this font. */
9578 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
9580 /* For the moment, width is not known. */
9581 list
= Fcons (Fcons (tem
, Qnil
), list
);
9586 if (!try_XLoadQueryFont
)
9589 XFreeFontNames (names
);
9594 /* Now store the result in the cache. */
9595 XSETCDR (dpyinfo
->name_list_element
,
9596 Fcons (Fcons (key
, list
), XCDR (dpyinfo
->name_list_element
)));
9599 if (NILP (list
)) continue; /* Try the remaining alternatives. */
9601 newlist
= second_best
= Qnil
;
9602 /* Make a list of the fonts that have the right width. */
9603 for (; CONSP (list
); list
= XCDR (list
))
9609 if (!CONSP (tem
) || NILP (XCAR (tem
)))
9613 newlist
= Fcons (XCAR (tem
), newlist
);
9617 if (!INTEGERP (XCDR (tem
)))
9619 /* Since we have not yet known the size of this font, we
9620 must try slow function call XLoadQueryFont. */
9621 XFontStruct
*thisinfo
;
9624 count
= x_catch_errors (dpy
);
9625 thisinfo
= XLoadQueryFont (dpy
,
9626 SDATA (XCAR (tem
)));
9627 if (x_had_errors_p (dpy
))
9629 /* This error is perhaps due to insufficient memory on X
9630 server. Let's just ignore it. */
9632 x_clear_errors (dpy
);
9634 x_uncatch_errors (dpy
, count
);
9640 (thisinfo
->min_bounds
.width
== 0
9642 : make_number (thisinfo
->max_bounds
.width
)));
9644 XFreeFont (dpy
, thisinfo
);
9648 /* For unknown reason, the previous call of XListFont had
9649 returned a font which can't be opened. Record the size
9650 as 0 not to try to open it again. */
9651 XSETCDR (tem
, make_number (0));
9654 found_size
= XINT (XCDR (tem
));
9655 if (found_size
== size
)
9656 newlist
= Fcons (XCAR (tem
), newlist
);
9657 else if (found_size
> 0)
9659 if (NILP (second_best
))
9661 else if (found_size
< size
)
9663 if (XINT (XCDR (second_best
)) > size
9664 || XINT (XCDR (second_best
)) < found_size
)
9669 if (XINT (XCDR (second_best
)) > size
9670 && XINT (XCDR (second_best
)) > found_size
)
9675 if (!NILP (newlist
))
9677 else if (!NILP (second_best
))
9679 newlist
= Fcons (XCAR (second_best
), Qnil
);
9690 /* Check that FONT is valid on frame F. It is if it can be found in F's
9694 x_check_font (f
, font
)
9699 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9701 xassert (font
!= NULL
);
9703 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9704 if (dpyinfo
->font_table
[i
].name
9705 && font
== dpyinfo
->font_table
[i
].font
)
9708 xassert (i
< dpyinfo
->n_fonts
);
9711 #endif /* GLYPH_DEBUG != 0 */
9713 /* Set *W to the minimum width, *H to the minimum font height of FONT.
9714 Note: There are (broken) X fonts out there with invalid XFontStruct
9715 min_bounds contents. For example, handa@etl.go.jp reports that
9716 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
9717 have font->min_bounds.width == 0. */
9720 x_font_min_bounds (font
, w
, h
)
9724 *h
= FONT_HEIGHT (font
);
9725 *w
= font
->min_bounds
.width
;
9727 /* Try to handle the case where FONT->min_bounds has invalid
9728 contents. Since the only font known to have invalid min_bounds
9729 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
9731 *w
= font
->max_bounds
.width
;
9735 /* Compute the smallest character width and smallest font height over
9736 all fonts available on frame F. Set the members smallest_char_width
9737 and smallest_font_height in F's x_display_info structure to
9738 the values computed. Value is non-zero if smallest_font_height or
9739 smallest_char_width become smaller than they were before. */
9742 x_compute_min_glyph_bounds (f
)
9746 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9748 int old_width
= dpyinfo
->smallest_char_width
;
9749 int old_height
= dpyinfo
->smallest_font_height
;
9751 dpyinfo
->smallest_font_height
= 100000;
9752 dpyinfo
->smallest_char_width
= 100000;
9754 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9755 if (dpyinfo
->font_table
[i
].name
)
9757 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
9760 font
= (XFontStruct
*) fontp
->font
;
9761 xassert (font
!= (XFontStruct
*) ~0);
9762 x_font_min_bounds (font
, &w
, &h
);
9764 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
9765 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
9768 xassert (dpyinfo
->smallest_char_width
> 0
9769 && dpyinfo
->smallest_font_height
> 0);
9771 return (dpyinfo
->n_fonts
== 1
9772 || dpyinfo
->smallest_char_width
< old_width
9773 || dpyinfo
->smallest_font_height
< old_height
);
9777 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9778 pointer to the structure font_info while allocating it dynamically.
9779 If SIZE is 0, load any size of font.
9780 If loading is failed, return NULL. */
9783 x_load_font (f
, fontname
, size
)
9785 register char *fontname
;
9788 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9789 Lisp_Object font_names
;
9792 /* Get a list of all the fonts that match this name. Once we
9793 have a list of matching fonts, we compare them against the fonts
9794 we already have by comparing names. */
9795 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
9797 if (!NILP (font_names
))
9802 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
9803 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
9804 if (dpyinfo
->font_table
[i
].name
9805 && (!strcmp (dpyinfo
->font_table
[i
].name
,
9806 SDATA (XCAR (tail
)))
9807 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
9808 SDATA (XCAR (tail
)))))
9809 return (dpyinfo
->font_table
+ i
);
9812 /* Load the font and add it to the table. */
9816 struct font_info
*fontp
;
9817 unsigned long value
;
9820 /* If we have found fonts by x_list_font, load one of them. If
9821 not, we still try to load a font by the name given as FONTNAME
9822 because XListFonts (called in x_list_font) of some X server has
9823 a bug of not finding a font even if the font surely exists and
9824 is loadable by XLoadQueryFont. */
9825 if (size
> 0 && !NILP (font_names
))
9826 fontname
= (char *) SDATA (XCAR (font_names
));
9829 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
9830 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
9831 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
9833 /* This error is perhaps due to insufficient memory on X
9834 server. Let's just ignore it. */
9836 x_clear_errors (FRAME_X_DISPLAY (f
));
9838 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
9843 /* Find a free slot in the font table. */
9844 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
9845 if (dpyinfo
->font_table
[i
].name
== NULL
)
9848 /* If no free slot found, maybe enlarge the font table. */
9849 if (i
== dpyinfo
->n_fonts
9850 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
9853 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
9854 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
9856 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
9859 fontp
= dpyinfo
->font_table
+ i
;
9860 if (i
== dpyinfo
->n_fonts
)
9863 /* Now fill in the slots of *FONTP. */
9865 bzero (fontp
, sizeof (*fontp
));
9867 fontp
->font_idx
= i
;
9868 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
9869 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
9871 /* Try to get the full name of FONT. Put it in FULL_NAME. */
9873 if (XGetFontProperty (font
, XA_FONT
, &value
))
9875 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
9879 /* Count the number of dashes in the "full name".
9880 If it is too few, this isn't really the font's full name,
9882 In X11R4, the fonts did not come with their canonical names
9893 full_name
= (char *) xmalloc (p
- name
+ 1);
9894 bcopy (name
, full_name
, p
- name
+ 1);
9901 fontp
->full_name
= full_name
;
9903 fontp
->full_name
= fontp
->name
;
9905 fontp
->size
= font
->max_bounds
.width
;
9906 fontp
->height
= FONT_HEIGHT (font
);
9908 if (NILP (font_names
))
9910 /* We come here because of a bug of XListFonts mentioned at
9911 the head of this block. Let's store this information in
9912 the cache for x_list_fonts. */
9913 Lisp_Object lispy_name
= build_string (fontname
);
9914 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
9915 Lisp_Object key
= Fcons (Fcons (lispy_name
, make_number (256)),
9918 XSETCDR (dpyinfo
->name_list_element
,
9920 Fcons (Fcons (lispy_full_name
,
9921 make_number (fontp
->size
)),
9923 XCDR (dpyinfo
->name_list_element
)));
9926 key
= Fcons (Fcons (lispy_full_name
, make_number (256)),
9928 XSETCDR (dpyinfo
->name_list_element
,
9930 Fcons (Fcons (lispy_full_name
,
9931 make_number (fontp
->size
)),
9933 XCDR (dpyinfo
->name_list_element
)));
9937 /* The slot `encoding' specifies how to map a character
9938 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9939 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9940 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9941 2:0xA020..0xFF7F). For the moment, we don't know which charset
9942 uses this font. So, we set information in fontp->encoding[1]
9943 which is never used by any charset. If mapping can't be
9944 decided, set FONT_ENCODING_NOT_DECIDED. */
9946 = (font
->max_byte1
== 0
9948 ? (font
->min_char_or_byte2
< 0x80
9949 ? (font
->max_char_or_byte2
< 0x80
9950 ? 0 /* 0x20..0x7F */
9951 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
9952 : 1) /* 0xA0..0xFF */
9954 : (font
->min_byte1
< 0x80
9955 ? (font
->max_byte1
< 0x80
9956 ? (font
->min_char_or_byte2
< 0x80
9957 ? (font
->max_char_or_byte2
< 0x80
9958 ? 0 /* 0x2020..0x7F7F */
9959 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
9960 : 3) /* 0x20A0..0x7FFF */
9961 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
9962 : (font
->min_char_or_byte2
< 0x80
9963 ? (font
->max_char_or_byte2
< 0x80
9964 ? 2 /* 0xA020..0xFF7F */
9965 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
9966 : 1))); /* 0xA0A0..0xFFFF */
9968 fontp
->baseline_offset
9969 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
9970 ? (long) value
: 0);
9971 fontp
->relative_compose
9972 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
9973 ? (long) value
: 0);
9974 fontp
->default_ascent
9975 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
9976 ? (long) value
: 0);
9978 /* Set global flag fonts_changed_p to non-zero if the font loaded
9979 has a character with a smaller width than any other character
9980 before, or if the font loaded has a smaller height than any
9981 other font loaded before. If this happens, it will make a
9982 glyph matrix reallocation necessary. */
9983 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
9990 /* Return a pointer to struct font_info of a font named FONTNAME for
9991 frame F. If no such font is loaded, return NULL. */
9994 x_query_font (f
, fontname
)
9996 register char *fontname
;
9998 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10001 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10002 if (dpyinfo
->font_table
[i
].name
10003 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
10004 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
10005 return (dpyinfo
->font_table
+ i
);
10010 /* Find a CCL program for a font specified by FONTP, and set the member
10011 `encoder' of the structure. */
10014 x_find_ccl_program (fontp
)
10015 struct font_info
*fontp
;
10017 Lisp_Object list
, elt
;
10020 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
10024 && STRINGP (XCAR (elt
))
10025 && ((fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
10027 || (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->full_name
)
10034 struct ccl_program
*ccl
10035 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
10037 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
10040 fontp
->font_encoder
= ccl
;
10046 /***********************************************************************
10048 ***********************************************************************/
10050 #ifdef USE_X_TOOLKIT
10051 static XrmOptionDescRec emacs_options
[] = {
10052 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
10053 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
10055 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10056 XrmoptionSepArg
, NULL
},
10057 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
10059 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10060 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10061 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
10062 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10063 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
10064 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
10065 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
10067 #endif /* USE_X_TOOLKIT */
10069 static int x_initialized
;
10071 #ifdef MULTI_KBOARD
10072 /* Test whether two display-name strings agree up to the dot that separates
10073 the screen number from the server number. */
10075 same_x_server (name1
, name2
)
10076 const char *name1
, *name2
;
10078 int seen_colon
= 0;
10079 const unsigned char *system_name
= SDATA (Vsystem_name
);
10080 int system_name_length
= strlen (system_name
);
10081 int length_until_period
= 0;
10083 while (system_name
[length_until_period
] != 0
10084 && system_name
[length_until_period
] != '.')
10085 length_until_period
++;
10087 /* Treat `unix' like an empty host name. */
10088 if (! strncmp (name1
, "unix:", 5))
10090 if (! strncmp (name2
, "unix:", 5))
10092 /* Treat this host's name like an empty host name. */
10093 if (! strncmp (name1
, system_name
, system_name_length
)
10094 && name1
[system_name_length
] == ':')
10095 name1
+= system_name_length
;
10096 if (! strncmp (name2
, system_name
, system_name_length
)
10097 && name2
[system_name_length
] == ':')
10098 name2
+= system_name_length
;
10099 /* Treat this host's domainless name like an empty host name. */
10100 if (! strncmp (name1
, system_name
, length_until_period
)
10101 && name1
[length_until_period
] == ':')
10102 name1
+= length_until_period
;
10103 if (! strncmp (name2
, system_name
, length_until_period
)
10104 && name2
[length_until_period
] == ':')
10105 name2
+= length_until_period
;
10107 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
10111 if (seen_colon
&& *name1
== '.')
10115 && (*name1
== '.' || *name1
== '\0')
10116 && (*name2
== '.' || *name2
== '\0'));
10120 /* Count number of set bits in mask and number of bits to shift to
10121 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10124 get_bits_and_offset (mask
, bits
, offset
)
10125 unsigned long mask
;
10132 while (!(mask
& 1))
10148 struct x_display_info
*
10149 x_term_init (display_name
, xrm_option
, resource_name
)
10150 Lisp_Object display_name
;
10152 char *resource_name
;
10156 struct display
*display
;
10157 struct x_display_info
*dpyinfo
;
10162 if (!x_initialized
)
10170 #define NUM_ARGV 10
10172 char *argv
[NUM_ARGV
];
10173 char **argv2
= argv
;
10176 if (x_initialized
++ > 1)
10178 /* Opening another display. If xg_display_open returns less
10179 than zero, we are probably on GTK 2.0, which can only handle
10180 one display. GTK 2.2 or later can handle more than one. */
10181 if (xg_display_open (SDATA (display_name
), &dpy
) < 0)
10182 error ("Sorry, this version of GTK can only handle one display");
10186 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10190 argv
[argc
++] = initial_argv
[0];
10192 if (! NILP (display_name
))
10194 argv
[argc
++] = "--display";
10195 argv
[argc
++] = SDATA (display_name
);
10198 argv
[argc
++] = "--name";
10199 argv
[argc
++] = resource_name
;
10202 XSetLocaleModifiers ("");
10205 gtk_init (&argc
, &argv2
);
10207 /* gtk_init does set_locale. We must fix locale after calling it. */
10211 dpy
= GDK_DISPLAY ();
10213 /* NULL window -> events for all windows go to our function */
10214 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
10216 /* Load our own gtkrc if it exists. */
10218 struct gcpro gcpro1
, gcpro2
;
10219 char *file
= "~/.emacs.d/gtkrc";
10220 Lisp_Object s
, abs_file
;
10222 GCPRO2 (s
, abs_file
);
10223 s
= make_string (file
, strlen (file
));
10224 abs_file
= Fexpand_file_name (s
, Qnil
);
10226 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
10227 gtk_rc_parse (SDATA (abs_file
));
10232 XSetErrorHandler (x_error_handler
);
10233 XSetIOErrorHandler (x_io_error_quitter
);
10236 #else /* not USE_GTK */
10237 #ifdef USE_X_TOOLKIT
10238 /* weiner@footloose.sps.mot.com reports that this causes
10240 X protocol error: BadAtom (invalid Atom parameter)
10241 on protocol request 18skiloaf.
10242 So let's not use it until R6. */
10243 #ifdef HAVE_X11XTR6
10244 XtSetLanguageProc (NULL
, NULL
, NULL
);
10255 argv
[argc
++] = "-xrm";
10256 argv
[argc
++] = xrm_option
;
10258 turn_on_atimers (0);
10259 dpy
= XtOpenDisplay (Xt_app_con
, SDATA (display_name
),
10260 resource_name
, EMACS_CLASS
,
10261 emacs_options
, XtNumber (emacs_options
),
10263 turn_on_atimers (1);
10265 #ifdef HAVE_X11XTR6
10266 /* I think this is to compensate for XtSetLanguageProc. */
10271 #else /* not USE_X_TOOLKIT */
10273 XSetLocaleModifiers ("");
10275 dpy
= XOpenDisplay (SDATA (display_name
));
10276 #endif /* not USE_X_TOOLKIT */
10277 #endif /* not USE_GTK*/
10279 /* Detect failure. */
10286 /* We have definitely succeeded. Record the new connection. */
10288 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
10289 bzero (dpyinfo
, sizeof *dpyinfo
);
10291 display
= x_create_frame_display (dpyinfo
);
10293 #ifdef MULTI_KBOARD
10295 struct x_display_info
*share
;
10298 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
10299 share
= share
->next
, tail
= XCDR (tail
))
10300 if (same_x_server (SDATA (XCAR (XCAR (tail
))),
10301 SDATA (display_name
)))
10304 dpyinfo
->kboard
= share
->kboard
;
10307 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
10308 init_kboard (dpyinfo
->kboard
);
10309 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
10311 char *vendor
= ServerVendor (dpy
);
10313 dpyinfo
->kboard
->Vsystem_key_alist
10314 = call1 (Qvendor_specific_keysyms
,
10315 build_string (vendor
? vendor
: ""));
10319 dpyinfo
->kboard
->next_kboard
= all_kboards
;
10320 all_kboards
= dpyinfo
->kboard
;
10321 /* Don't let the initial kboard remain current longer than necessary.
10322 That would cause problems if a file loaded on startup tries to
10323 prompt in the mini-buffer. */
10324 if (current_kboard
== initial_kboard
)
10325 current_kboard
= dpyinfo
->kboard
;
10327 dpyinfo
->kboard
->reference_count
++;
10331 /* Put this display on the chain. */
10332 dpyinfo
->next
= x_display_list
;
10333 x_display_list
= dpyinfo
;
10335 /* Put it on x_display_name_list as well, to keep them parallel. */
10336 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
10337 x_display_name_list
);
10338 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10340 dpyinfo
->display
= dpy
;
10342 /* Set the name of the display. */
10343 display
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
10344 strncpy (display
->name
, SDATA (display_name
), SBYTES (display_name
));
10345 display
->name
[SBYTES (display_name
)] = 0;
10348 XSetAfterFunction (x_current_display
, x_trace_wire
);
10352 = (char *) xmalloc (SBYTES (Vinvocation_name
)
10353 + SBYTES (Vsystem_name
)
10355 sprintf (dpyinfo
->x_id_name
, "%s@%s",
10356 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10358 /* Figure out which modifier bits mean what. */
10359 x_find_modifier_meanings (dpyinfo
);
10361 /* Get the scroll bar cursor. */
10363 /* We must create a GTK cursor, it is required for GTK widgets. */
10364 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10365 #endif /* USE_GTK */
10367 dpyinfo
->vertical_scroll_bar_cursor
10368 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10370 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10371 resource_name
, EMACS_CLASS
);
10372 #ifdef HAVE_XRMSETDATABASE
10373 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10375 dpyinfo
->display
->db
= xrdb
;
10377 /* Put the rdb where we can find it in a way that works on
10379 dpyinfo
->xrdb
= xrdb
;
10381 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10382 DefaultScreen (dpyinfo
->display
));
10383 select_visual (dpyinfo
);
10384 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10385 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
10386 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
10387 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10388 dpyinfo
->client_leader_window
= 0;
10389 dpyinfo
->grabbed
= 0;
10390 dpyinfo
->reference_count
= 0;
10391 dpyinfo
->icon_bitmap_id
= -1;
10392 dpyinfo
->font_table
= NULL
;
10393 dpyinfo
->n_fonts
= 0;
10394 dpyinfo
->font_table_size
= 0;
10395 dpyinfo
->bitmaps
= 0;
10396 dpyinfo
->bitmaps_size
= 0;
10397 dpyinfo
->bitmaps_last
= 0;
10398 dpyinfo
->scratch_cursor_gc
= 0;
10399 dpyinfo
->mouse_face_mouse_frame
= 0;
10400 dpyinfo
->mouse_face_deferred_gc
= 0;
10401 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10402 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10403 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10404 dpyinfo
->mouse_face_window
= Qnil
;
10405 dpyinfo
->mouse_face_overlay
= Qnil
;
10406 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
10407 dpyinfo
->mouse_face_defer
= 0;
10408 dpyinfo
->mouse_face_hidden
= 0;
10409 dpyinfo
->x_focus_frame
= 0;
10410 dpyinfo
->x_focus_event_frame
= 0;
10411 dpyinfo
->x_highlight_frame
= 0;
10412 dpyinfo
->image_cache
= make_image_cache ();
10413 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10415 /* See if we can construct pixel values from RGB values. */
10416 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
10417 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
10419 if (dpyinfo
->visual
->class == TrueColor
)
10421 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10422 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10423 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10424 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10425 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10426 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10429 /* See if a private colormap is requested. */
10430 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10432 if (dpyinfo
->visual
->class == PseudoColor
)
10435 value
= display_x_get_resource (dpyinfo
,
10436 build_string ("privateColormap"),
10437 build_string ("PrivateColormap"),
10439 if (STRINGP (value
)
10440 && (!strcmp (SDATA (value
), "true")
10441 || !strcmp (SDATA (value
), "on")))
10442 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10446 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10447 dpyinfo
->visual
, AllocNone
);
10450 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10451 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10452 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10453 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10454 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10455 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10456 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10457 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10458 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10461 dpyinfo
->Xatom_wm_protocols
10462 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
10463 dpyinfo
->Xatom_wm_take_focus
10464 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
10465 dpyinfo
->Xatom_wm_save_yourself
10466 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
10467 dpyinfo
->Xatom_wm_delete_window
10468 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
10469 dpyinfo
->Xatom_wm_change_state
10470 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
10471 dpyinfo
->Xatom_wm_configure_denied
10472 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
10473 dpyinfo
->Xatom_wm_window_moved
10474 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
10475 dpyinfo
->Xatom_wm_client_leader
10476 = XInternAtom (dpyinfo
->display
, "WM_CLIENT_LEADER", False
);
10477 dpyinfo
->Xatom_editres
10478 = XInternAtom (dpyinfo
->display
, "Editres", False
);
10479 dpyinfo
->Xatom_CLIPBOARD
10480 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
10481 dpyinfo
->Xatom_TIMESTAMP
10482 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
10483 dpyinfo
->Xatom_TEXT
10484 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
10485 dpyinfo
->Xatom_COMPOUND_TEXT
10486 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
10487 dpyinfo
->Xatom_UTF8_STRING
10488 = XInternAtom (dpyinfo
->display
, "UTF8_STRING", False
);
10489 dpyinfo
->Xatom_DELETE
10490 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
10491 dpyinfo
->Xatom_MULTIPLE
10492 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
10493 dpyinfo
->Xatom_INCR
10494 = XInternAtom (dpyinfo
->display
, "INCR", False
);
10495 dpyinfo
->Xatom_EMACS_TMP
10496 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
10497 dpyinfo
->Xatom_TARGETS
10498 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
10499 dpyinfo
->Xatom_NULL
10500 = XInternAtom (dpyinfo
->display
, "NULL", False
);
10501 dpyinfo
->Xatom_ATOM_PAIR
10502 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
10503 /* For properties of font. */
10504 dpyinfo
->Xatom_PIXEL_SIZE
10505 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
10506 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
10507 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
10508 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
10509 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
10510 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
10511 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
10513 /* Ghostscript support. */
10514 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
10515 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
10517 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
10520 dpyinfo
->cut_buffers_initialized
= 0;
10522 connection
= ConnectionNumber (dpyinfo
->display
);
10523 dpyinfo
->connection
= connection
;
10528 null_bits
[0] = 0x00;
10530 dpyinfo
->null_pixel
10531 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10532 null_bits
, 1, 1, (long) 0, (long) 0,
10537 extern int gray_bitmap_width
, gray_bitmap_height
;
10538 extern char *gray_bitmap_bits
;
10540 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10542 gray_bitmap_width
, gray_bitmap_height
,
10543 (unsigned long) 1, (unsigned long) 0, 1);
10547 xim_initialize (dpyinfo
, resource_name
);
10550 #ifdef subprocesses
10551 /* This is only needed for distinguishing keyboard and process input. */
10552 if (connection
!= 0)
10553 add_keyboard_wait_descriptor (connection
);
10556 #ifndef F_SETOWN_BUG
10558 #ifdef F_SETOWN_SOCK_NEG
10559 /* stdin is a socket here */
10560 fcntl (connection
, F_SETOWN
, -getpid ());
10561 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10562 fcntl (connection
, F_SETOWN
, getpid ());
10563 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10564 #endif /* ! defined (F_SETOWN) */
10565 #endif /* F_SETOWN_BUG */
10568 if (interrupt_input
)
10569 init_sigio (connection
);
10570 #endif /* ! defined (SIGIO) */
10573 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
10574 /* Make sure that we have a valid font for dialog boxes
10575 so that Xt does not crash. */
10577 Display
*dpy
= dpyinfo
->display
;
10578 XrmValue d
, fr
, to
;
10582 d
.addr
= (XPointer
)&dpy
;
10583 d
.size
= sizeof (Display
*);
10584 fr
.addr
= XtDefaultFont
;
10585 fr
.size
= sizeof (XtDefaultFont
);
10586 to
.size
= sizeof (Font
*);
10587 to
.addr
= (XPointer
)&font
;
10588 count
= x_catch_errors (dpy
);
10589 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10591 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
10592 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10593 x_uncatch_errors (dpy
, count
);
10598 /* See if we should run in synchronous mode. This is useful
10599 for debugging X code. */
10602 value
= display_x_get_resource (dpyinfo
,
10603 build_string ("synchronous"),
10604 build_string ("Synchronous"),
10606 if (STRINGP (value
)
10607 && (!strcmp (SDATA (value
), "true")
10608 || !strcmp (SDATA (value
), "on")))
10609 XSynchronize (dpyinfo
->display
, True
);
10614 value
= display_x_get_resource (dpyinfo
,
10615 build_string ("useXIM"),
10616 build_string ("UseXIM"),
10619 if (STRINGP (value
)
10620 && (!strcmp (XSTRING (value
)->data
, "false")
10621 || !strcmp (XSTRING (value
)->data
, "off")))
10624 if (STRINGP (value
)
10625 && (!strcmp (XSTRING (value
)->data
, "true")
10626 || !strcmp (XSTRING (value
)->data
, "on")))
10632 /* Only do this for the first display. */
10633 if (x_initialized
== 1)
10634 x_session_initialize (dpyinfo
);
10642 /* Get rid of display DPYINFO, assuming all frames are already gone,
10643 and without sending any more commands to the X server. */
10646 x_delete_display (dpyinfo
)
10647 struct x_display_info
*dpyinfo
;
10652 /* Delete the generic struct display for this X display. */
10654 for (d
= display_list
; d
; d
= d
->next_display
)
10655 if (d
->type
== output_x_window
&& d
->display_info
.x
== dpyinfo
)
10657 delete_display (d
);
10662 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
10664 /* Discard this display from x_display_name_list and x_display_list.
10665 We can't use Fdelq because that can quit. */
10666 if (! NILP (x_display_name_list
)
10667 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10668 x_display_name_list
= XCDR (x_display_name_list
);
10673 tail
= x_display_name_list
;
10674 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10676 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10678 XSETCDR (tail
, XCDR (XCDR (tail
)));
10681 tail
= XCDR (tail
);
10685 if (next_noop_dpyinfo
== dpyinfo
)
10686 next_noop_dpyinfo
= dpyinfo
->next
;
10688 if (x_display_list
== dpyinfo
)
10689 x_display_list
= dpyinfo
->next
;
10692 struct x_display_info
*tail
;
10694 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10695 if (tail
->next
== dpyinfo
)
10696 tail
->next
= tail
->next
->next
;
10699 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10700 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10701 XrmDestroyDatabase (dpyinfo
->xrdb
);
10704 #ifdef MULTI_KBOARD
10705 if (--dpyinfo
->kboard
->reference_count
== 0)
10706 delete_kboard (dpyinfo
->kboard
);
10710 xim_close_dpy (dpyinfo
);
10713 /* Free the font names in the font table. */
10714 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10715 if (dpyinfo
->font_table
[i
].name
)
10717 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10718 xfree (dpyinfo
->font_table
[i
].full_name
);
10719 xfree (dpyinfo
->font_table
[i
].name
);
10722 if (dpyinfo
->font_table
&& dpyinfo
->font_table
->font_encoder
)
10723 xfree (dpyinfo
->font_table
->font_encoder
);
10725 if (dpyinfo
->font_table
)
10726 xfree (dpyinfo
->font_table
);
10727 xfree (dpyinfo
->x_id_name
);
10728 xfree (dpyinfo
->color_cells
);
10732 #ifdef USE_X_TOOLKIT
10734 /* Atimer callback function for TIMER. Called every 0.1s to process
10735 Xt timeouts, if needed. We must avoid calling XtAppPending as
10736 much as possible because that function does an implicit XFlush
10737 that slows us down. */
10740 x_process_timeouts (timer
)
10741 struct atimer
*timer
;
10743 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10746 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10747 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10752 #endif /* USE_X_TOOLKIT */
10755 /* Set up use of X before we make the first connection. */
10757 extern frame_parm_handler x_frame_parm_handlers
[];
10759 static struct redisplay_interface x_redisplay_interface
=
10761 x_frame_parm_handlers
,
10765 x_clear_end_of_line
,
10767 x_after_update_window_line
,
10768 x_update_window_begin
,
10769 x_update_window_end
,
10775 0, /* flush_display_optional */
10777 x_clear_window_mouse_face
,
10778 x_get_glyph_overhangs
,
10779 x_fix_overlapping_area
,
10780 x_draw_fringe_bitmap
,
10781 0, /* define_fringe_bitmap */
10782 0, /* destroy_fringe_bitmap */
10785 x_compute_glyph_string_overhangs
,
10786 x_draw_glyph_string
,
10787 x_define_frame_cursor
,
10788 x_clear_frame_area
,
10789 x_draw_window_cursor
,
10790 x_draw_vertical_window_border
,
10791 x_shift_glyphs_for_insert
10795 /* This function is called when the last frame on a display is deleted. */
10797 x_delete_frame_display (struct display
*display
)
10799 /* We don't do anything, the connection to the X server must remain
10805 x_create_frame_display (struct x_display_info
*dpyinfo
)
10807 struct display
*display
;
10809 display
= create_display ();
10811 display
->type
= output_x_window
;
10812 display
->display_info
.x
= dpyinfo
;
10813 dpyinfo
->frame_display
= display
;
10815 display
->clear_frame_hook
= x_clear_frame
;
10816 display
->ins_del_lines_hook
= x_ins_del_lines
;
10817 display
->delete_glyphs_hook
= x_delete_glyphs
;
10818 display
->ring_bell_hook
= XTring_bell
;
10819 display
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
10820 display
->set_terminal_modes_hook
= XTset_terminal_modes
;
10821 display
->update_begin_hook
= x_update_begin
;
10822 display
->update_end_hook
= x_update_end
;
10823 display
->set_terminal_window_hook
= XTset_terminal_window
;
10824 display
->read_socket_hook
= XTread_socket
;
10825 display
->frame_up_to_date_hook
= XTframe_up_to_date
;
10826 display
->mouse_position_hook
= XTmouse_position
;
10827 display
->frame_rehighlight_hook
= XTframe_rehighlight
;
10828 display
->frame_raise_lower_hook
= XTframe_raise_lower
;
10829 display
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10830 display
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10831 display
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10832 display
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10834 display
->delete_frame_hook
= x_destroy_window
;
10835 display
->delete_display_hook
= x_delete_frame_display
;
10837 display
->rif
= &x_redisplay_interface
;
10838 display
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
10839 display
->char_ins_del_ok
= 1;
10840 display
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
10841 display
->fast_clear_end_of_line
= 1; /* X does this well. */
10842 display
->memory_below_frame
= 0; /* We don't remember what scrolls
10854 last_tool_bar_item
= -1;
10855 any_help_event_p
= 0;
10856 ignore_next_mouse_click_timeout
= 0;
10859 current_count
= -1;
10862 /* Try to use interrupt input; if we can't, then start polling. */
10863 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10865 #ifdef USE_X_TOOLKIT
10866 XtToolkitInitialize ();
10868 Xt_app_con
= XtCreateApplicationContext ();
10870 /* Register a converter from strings to pixels, which uses
10871 Emacs' color allocation infrastructure. */
10872 XtAppSetTypeConverter (Xt_app_con
,
10873 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10874 cvt_string_to_pixel_args
,
10875 XtNumber (cvt_string_to_pixel_args
),
10876 XtCacheByDisplay
, cvt_pixel_dtor
);
10878 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10880 /* Install an asynchronous timer that processes Xt timeout events
10881 every 0.1s. This is necessary because some widget sets use
10882 timeouts internally, for example the LessTif menu bar, or the
10883 Xaw3d scroll bar. When Xt timouts aren't processed, these
10884 widgets don't behave normally. */
10886 EMACS_TIME interval
;
10887 EMACS_SET_SECS_USECS (interval
, 0, 100000);
10888 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
10892 #ifdef USE_TOOLKIT_SCROLL_BARS
10894 xaw3d_arrow_scroll
= False
;
10895 xaw3d_pick_top
= True
;
10899 /* Note that there is no real way portable across R3/R4 to get the
10900 original error handler. */
10901 XSetErrorHandler (x_error_handler
);
10902 XSetIOErrorHandler (x_io_error_quitter
);
10904 /* Disable Window Change signals; they are handled by X events. */
10905 #if 0 /* Don't. We may want to open tty frames later. */
10907 signal (SIGWINCH
, SIG_DFL
);
10908 #endif /* SIGWINCH */
10911 signal (SIGPIPE
, x_connection_signal
);
10918 staticpro (&x_error_message_string
);
10919 x_error_message_string
= Qnil
;
10921 staticpro (&x_display_name_list
);
10922 x_display_name_list
= Qnil
;
10924 staticpro (&last_mouse_scroll_bar
);
10925 last_mouse_scroll_bar
= Qnil
;
10927 staticpro (&Qvendor_specific_keysyms
);
10928 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
10930 staticpro (&Qutf_8
);
10931 Qutf_8
= intern ("utf-8");
10932 staticpro (&Qlatin_1
);
10933 Qlatin_1
= intern ("latin-1");
10935 staticpro (&last_mouse_press_frame
);
10936 last_mouse_press_frame
= Qnil
;
10938 DEFVAR_BOOL ("x-use-underline-position-properties",
10939 &x_use_underline_position_properties
,
10940 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10941 nil means ignore them. If you encounter fonts with bogus
10942 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10943 to 4.1, set this to nil. */);
10944 x_use_underline_position_properties
= 1;
10946 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10947 &x_mouse_click_focus_ignore_position
,
10948 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
10949 This variable is only used when the window manager requires that you
10950 click on a frame to select it (give it focus). In that case, a value
10951 of nil, means that the selected window and cursor position changes to
10952 reflect the mouse click position, while a non-nil value means that the
10953 selected window or cursor position is preserved. */);
10954 x_mouse_click_focus_ignore_position
= 0;
10956 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10957 doc
: /* What X toolkit scroll bars Emacs uses.
10958 A value of nil means Emacs doesn't use X toolkit scroll bars.
10959 Otherwise, value is a symbol describing the X toolkit. */);
10960 #ifdef USE_TOOLKIT_SCROLL_BARS
10962 Vx_toolkit_scroll_bars
= intern ("motif");
10963 #elif defined HAVE_XAW3D
10964 Vx_toolkit_scroll_bars
= intern ("xaw3d");
10966 Vx_toolkit_scroll_bars
= intern ("gtk");
10968 Vx_toolkit_scroll_bars
= intern ("xaw");
10971 Vx_toolkit_scroll_bars
= Qnil
;
10974 staticpro (&last_mouse_motion_frame
);
10975 last_mouse_motion_frame
= Qnil
;
10977 Qmodifier_value
= intern ("modifier-value");
10978 Qalt
= intern ("alt");
10979 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10980 Qhyper
= intern ("hyper");
10981 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10982 Qmeta
= intern ("meta");
10983 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10984 Qsuper
= intern ("super");
10985 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10987 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym
,
10988 doc
: /* Which keys Emacs uses for the alt modifier.
10989 This should be one of the symbols `alt', `hyper', `meta', `super'.
10990 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10991 is nil, which is the same as `alt'. */);
10992 Vx_alt_keysym
= Qnil
;
10994 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym
,
10995 doc
: /* Which keys Emacs uses for the hyper modifier.
10996 This should be one of the symbols `alt', `hyper', `meta', `super'.
10997 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10998 default is nil, which is the same as `hyper'. */);
10999 Vx_hyper_keysym
= Qnil
;
11001 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym
,
11002 doc
: /* Which keys Emacs uses for the meta modifier.
11003 This should be one of the symbols `alt', `hyper', `meta', `super'.
11004 For example, `meta' means use the Meta_L and Meta_R keysyms. The
11005 default is nil, which is the same as `meta'. */);
11006 Vx_meta_keysym
= Qnil
;
11008 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym
,
11009 doc
: /* Which keys Emacs uses for the super modifier.
11010 This should be one of the symbols `alt', `hyper', `meta', `super'.
11011 For example, `super' means use the Super_L and Super_R keysyms. The
11012 default is nil, which is the same as `super'. */);
11013 Vx_super_keysym
= Qnil
;
11015 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table
,
11016 doc
: /* Hash table of character codes indexed by X keysym codes. */);
11017 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
11018 make_float (DEFAULT_REHASH_SIZE
),
11019 make_float (DEFAULT_REHASH_THRESHOLD
),
11023 #endif /* HAVE_X_WINDOWS */
11025 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
11026 (do not change this comment) */