1 /* X Communication module for terminals which understand the X protocol.
3 Copyright (C) 1989, 1993-2012 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
21 /* Xt features made by Fred Pierresteguy. */
31 #include "blockinput.h"
33 /* Need syssignal.h for various externs and definitions that may be required
34 by some configurations for calls to signal later in this source file. */
35 #include "syssignal.h"
37 /* This may include sys/types.h, and that somehow loses
38 if this is not done before the other system files. */
40 #include <X11/cursorfont.h>
42 /* Load sys/types.h if not already loaded.
43 In some systems loading it twice is suicidal. */
45 #include <sys/types.h>
48 #include <sys/ioctl.h>
57 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
58 /* #include <sys/param.h> */
61 #include "character.h"
64 #include "dispextern.h"
66 #include "termhooks.h"
69 #include "emacs-icon.h"
74 #include "intervals.h"
80 #include "xsettings.h"
82 #include "sysselect.h"
85 #include <X11/Shell.h>
88 #ifdef HAVE_SYS_TIME_H
97 #include <X11/Xproto.h>
102 #include "../lwlib/xlwmenu.h"
106 #if !defined (NO_EDITRES)
108 extern void _XEditResCheckMessages (Widget
, XtPointer
, XEvent
*, Boolean
*);
109 #endif /* not NO_EDITRES */
111 /* Include toolkit specific headers for the scroll bar widget. */
113 #ifdef USE_TOOLKIT_SCROLL_BARS
114 #if defined USE_MOTIF
115 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
116 #include <Xm/ScrollBar.h>
117 #else /* !USE_MOTIF i.e. use Xaw */
120 #include <X11/Xaw3d/Simple.h>
121 #include <X11/Xaw3d/Scrollbar.h>
122 #include <X11/Xaw3d/ThreeD.h>
123 #else /* !HAVE_XAW3D */
124 #include <X11/Xaw/Simple.h>
125 #include <X11/Xaw/Scrollbar.h>
126 #endif /* !HAVE_XAW3D */
128 #define XtNpickTop "pickTop"
129 #endif /* !XtNpickTop */
130 #endif /* !USE_MOTIF */
131 #endif /* USE_TOOLKIT_SCROLL_BARS */
133 #endif /* USE_X_TOOLKIT */
137 #ifndef XtNinitialState
138 #define XtNinitialState "initialState"
142 #include "bitmaps/gray.xbm"
144 /* Default to using XIM if available. */
148 int use_xim
= 0; /* configure --without-xim */
153 /* Non-zero means that a HELP_EVENT has been generated since Emacs
156 static int any_help_event_p
;
158 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
159 static Lisp_Object last_window
;
161 /* This is a chain of structures for all the X displays currently in
164 struct x_display_info
*x_display_list
;
166 /* This is a list of cons cells, each of the form (NAME
167 . FONT-LIST-CACHE), one for each element of x_display_list and in
168 the same order. NAME is the name of the frame. FONT-LIST-CACHE
169 records previous values returned by x-list-fonts. */
171 Lisp_Object x_display_name_list
;
173 /* Frame being updated by update_frame. This is declared in term.c.
174 This is set by update_begin and looked at by all the XT functions.
175 It is zero while not inside an update. In that case, the XT
176 functions assume that `selected_frame' is the frame to apply to. */
178 extern struct frame
*updating_frame
;
180 /* This is a frame waiting to be auto-raised, within XTread_socket. */
182 static struct frame
*pending_autoraise_frame
;
184 /* This is a frame waiting for an event matching mask, within XTread_socket. */
189 } pending_event_wait
;
192 /* The application context for Xt use. */
193 XtAppContext Xt_app_con
;
194 static String Xt_default_resources
[] = {0};
196 /* Non-zero means user is interacting with a toolkit scroll bar. */
198 static int toolkit_scroll_bar_interaction
;
199 #endif /* USE_X_TOOLKIT */
201 /* Non-zero timeout value means ignore next mouse click if it arrives
202 before that timeout elapses (i.e. as part of the same sequence of
203 events resulting from clicking on a frame to select it). */
205 static unsigned long ignore_next_mouse_click_timeout
;
209 Formerly, we used PointerMotionHintMask (in standard_event_mask)
210 so that we would have to call XQueryPointer after each MotionNotify
211 event to ask for another such event. However, this made mouse tracking
212 slow, and there was a bug that made it eventually stop.
214 Simply asking for MotionNotify all the time seems to work better.
216 In order to avoid asking for motion events and then throwing most
217 of them away or busy-polling the server for mouse positions, we ask
218 the server for pointer motion hints. This means that we get only
219 one event per group of mouse movements. "Groups" are delimited by
220 other kinds of events (focus changes and button clicks, for
221 example), or by XQueryPointer calls; when one of these happens, we
222 get another MotionNotify event the next time the mouse moves. This
223 is at least as efficient as getting motion events when mouse
224 tracking is on, and I suspect only negligibly worse when tracking
227 /* Where the mouse was last time we reported a mouse event. */
229 static XRectangle last_mouse_glyph
;
230 static FRAME_PTR last_mouse_glyph_frame
;
231 static Lisp_Object last_mouse_press_frame
;
233 /* The scroll bar in which the last X motion event occurred.
235 If the last X motion event occurred in a scroll bar, we set this so
236 XTmouse_position can know whether to report a scroll bar motion or
239 If the last X motion event didn't occur in a scroll bar, we set
240 this to Qnil, to tell XTmouse_position to return an ordinary motion
243 static Lisp_Object last_mouse_scroll_bar
;
245 /* This is a hack. We would really prefer that XTmouse_position would
246 return the time associated with the position it returns, but there
247 doesn't seem to be any way to wrest the time-stamp from the server
248 along with the position query. So, we just keep track of the time
249 of the last movement we received, and return that in hopes that
250 it's somewhat accurate. */
252 static Time last_mouse_movement_time
;
254 /* Time for last user interaction as returned in X events. */
256 static Time last_user_time
;
258 /* Incremented by XTread_socket whenever it really tries to read
261 static int volatile input_signal_count
;
263 /* Used locally within XTread_socket. */
265 static int x_noop_count
;
267 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
269 static Lisp_Object Qvendor_specific_keysyms
;
270 static Lisp_Object Qlatin_1
;
273 /* The name of the Emacs icon file. */
274 static Lisp_Object xg_default_icon_file
;
276 /* Used in gtkutil.c. */
277 Lisp_Object Qx_gtk_map_stock
;
280 /* Some functions take this as char *, not const char *. */
281 static char emacs_class
[] = EMACS_CLASS
;
285 XEMBED_MAPPED
= 1 << 0
290 XEMBED_EMBEDDED_NOTIFY
= 0,
291 XEMBED_WINDOW_ACTIVATE
= 1,
292 XEMBED_WINDOW_DEACTIVATE
= 2,
293 XEMBED_REQUEST_FOCUS
= 3,
295 XEMBED_FOCUS_OUT
= 5,
296 XEMBED_FOCUS_NEXT
= 6,
297 XEMBED_FOCUS_PREV
= 7,
299 XEMBED_MODALITY_ON
= 10,
300 XEMBED_MODALITY_OFF
= 11,
301 XEMBED_REGISTER_ACCELERATOR
= 12,
302 XEMBED_UNREGISTER_ACCELERATOR
= 13,
303 XEMBED_ACTIVATE_ACCELERATOR
= 14
306 /* Used in x_flush. */
308 static int x_alloc_nearest_color_1 (Display
*, Colormap
, XColor
*);
309 static void x_set_window_size_1 (struct frame
*, int, int, int);
310 static void x_raise_frame (struct frame
*);
311 static void x_lower_frame (struct frame
*);
312 static const XColor
*x_color_cells (Display
*, int *);
313 static void x_update_window_end (struct window
*, int, int);
315 static int x_io_error_quitter (Display
*);
316 static struct terminal
*x_create_terminal (struct x_display_info
*);
317 void x_delete_terminal (struct terminal
*);
318 static void x_update_end (struct frame
*);
319 static void XTframe_up_to_date (struct frame
*);
320 static void XTset_terminal_modes (struct terminal
*);
321 static void XTreset_terminal_modes (struct terminal
*);
322 static void x_clear_frame (struct frame
*);
323 static void x_ins_del_lines (struct frame
*, int, int) NO_RETURN
;
324 static void frame_highlight (struct frame
*);
325 static void frame_unhighlight (struct frame
*);
326 static void x_new_focus_frame (struct x_display_info
*, struct frame
*);
327 static void x_focus_changed (int, int, struct x_display_info
*,
328 struct frame
*, struct input_event
*);
329 static void x_detect_focus_change (struct x_display_info
*,
330 XEvent
*, struct input_event
*);
331 static void XTframe_rehighlight (struct frame
*);
332 static void x_frame_rehighlight (struct x_display_info
*);
333 static void x_draw_hollow_cursor (struct window
*, struct glyph_row
*);
334 static void x_draw_bar_cursor (struct window
*, struct glyph_row
*, int,
335 enum text_cursor_kinds
);
337 static void x_clip_to_row (struct window
*, struct glyph_row
*, int, GC
);
338 static void x_flush (struct frame
*f
);
339 static void x_update_begin (struct frame
*);
340 static void x_update_window_begin (struct window
*);
341 static void x_after_update_window_line (struct glyph_row
*);
342 static struct scroll_bar
*x_window_to_scroll_bar (Display
*, Window
);
343 static void x_scroll_bar_report_motion (struct frame
**, Lisp_Object
*,
344 enum scroll_bar_part
*,
345 Lisp_Object
*, Lisp_Object
*,
347 static int x_handle_net_wm_state (struct frame
*, XPropertyEvent
*);
348 static void x_check_fullscreen (struct frame
*);
349 static void x_check_expected_move (struct frame
*, int, int);
350 static void x_sync_with_move (struct frame
*, int, int, int);
351 static int handle_one_xevent (struct x_display_info
*, XEvent
*,
352 int *, struct input_event
*);
354 static int x_dispatch_event (XEvent
*, Display
*);
356 /* Don't declare this NO_RETURN because we want no
357 interference with debugging failing X calls. */
358 static void x_connection_closed (Display
*, const char *);
359 static void x_wm_set_window_state (struct frame
*, int);
360 static void x_wm_set_icon_pixmap (struct frame
*, ptrdiff_t);
361 static void x_initialize (void);
364 /* Flush display of frame F, or of all frames if F is null. */
367 x_flush (struct frame
*f
)
369 /* Don't call XFlush when it is not safe to redisplay; the X
370 connection may be broken. */
371 if (!NILP (Vinhibit_redisplay
))
377 Lisp_Object rest
, frame
;
378 FOR_EACH_FRAME (rest
, frame
)
379 if (FRAME_X_P (XFRAME (frame
)))
380 x_flush (XFRAME (frame
));
382 else if (FRAME_X_P (f
))
383 XFlush (FRAME_X_DISPLAY (f
));
388 /* Remove calls to XFlush by defining XFlush to an empty replacement.
389 Calls to XFlush should be unnecessary because the X output buffer
390 is flushed automatically as needed by calls to XPending,
391 XNextEvent, or XWindowEvent according to the XFlush man page.
392 XTread_socket calls XPending. Removing XFlush improves
395 #define XFlush(DISPLAY) (void) 0
398 /***********************************************************************
400 ***********************************************************************/
404 /* This is a function useful for recording debugging information about
405 the sequence of occurrences in this file. */
413 struct record event_record
[100];
415 int event_record_index
;
418 record_event (char *locus
, int type
)
420 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
421 event_record_index
= 0;
423 event_record
[event_record_index
].locus
= locus
;
424 event_record
[event_record_index
].type
= type
;
425 event_record_index
++;
432 /* Return the struct x_display_info corresponding to DPY. */
434 struct x_display_info
*
435 x_display_info_for_display (Display
*dpy
)
437 struct x_display_info
*dpyinfo
;
439 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
440 if (dpyinfo
->display
== dpy
)
447 x_find_topmost_parent (struct frame
*f
)
449 struct x_output
*x
= f
->output_data
.x
;
450 Window win
= None
, wi
= x
->parent_desc
;
451 Display
*dpy
= FRAME_X_DISPLAY (f
);
453 while (wi
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
457 unsigned int nchildren
;
460 XQueryTree (dpy
, win
, &root
, &wi
, &children
, &nchildren
);
467 #define OPAQUE 0xffffffff
470 x_set_frame_alpha (struct frame
*f
)
472 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
473 Display
*dpy
= FRAME_X_DISPLAY (f
);
474 Window win
= FRAME_OUTER_WINDOW (f
);
476 double alpha_min
= 1.0;
480 if (dpyinfo
->x_highlight_frame
== f
)
485 if (FLOATP (Vframe_alpha_lower_limit
))
486 alpha_min
= XFLOAT_DATA (Vframe_alpha_lower_limit
);
487 else if (INTEGERP (Vframe_alpha_lower_limit
))
488 alpha_min
= (XINT (Vframe_alpha_lower_limit
)) / 100.0;
492 else if (alpha
> 1.0)
494 else if (0.0 <= alpha
&& alpha
< alpha_min
&& alpha_min
<= 1.0)
497 opac
= alpha
* OPAQUE
;
499 x_catch_errors (dpy
);
501 /* If there is a parent from the window manager, put the property there
502 also, to work around broken window managers that fail to do that.
503 Do this unconditionally as this function is called on reparent when
504 alpha has not changed on the frame. */
506 parent
= x_find_topmost_parent (f
);
508 XChangeProperty (dpy
, parent
, dpyinfo
->Xatom_net_wm_window_opacity
,
509 XA_CARDINAL
, 32, PropModeReplace
,
510 (unsigned char *) &opac
, 1L);
512 /* return unless necessary */
517 unsigned long n
, left
;
519 rc
= XGetWindowProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
520 0L, 1L, False
, XA_CARDINAL
,
521 &actual
, &format
, &n
, &left
,
524 if (rc
== Success
&& actual
!= None
)
526 unsigned long value
= *(unsigned long *)data
;
527 XFree ((void *) data
);
536 XChangeProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
537 XA_CARDINAL
, 32, PropModeReplace
,
538 (unsigned char *) &opac
, 1L);
543 x_display_pixel_height (struct x_display_info
*dpyinfo
)
545 return HeightOfScreen (dpyinfo
->screen
);
549 x_display_pixel_width (struct x_display_info
*dpyinfo
)
551 return WidthOfScreen (dpyinfo
->screen
);
555 /***********************************************************************
556 Starting and ending an update
557 ***********************************************************************/
559 /* Start an update of frame F. This function is installed as a hook
560 for update_begin, i.e. it is called when update_begin is called.
561 This function is called prior to calls to x_update_window_begin for
562 each window being updated. Currently, there is nothing to do here
563 because all interesting stuff is done on a window basis. */
566 x_update_begin (struct frame
*f
)
572 /* Start update of window W. Set the global variable updated_window
573 to the window being updated and set output_cursor to the cursor
577 x_update_window_begin (struct window
*w
)
579 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
580 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (f
);
583 set_output_cursor (&w
->cursor
);
587 if (f
== hlinfo
->mouse_face_mouse_frame
)
589 /* Don't do highlighting for mouse motion during the update. */
590 hlinfo
->mouse_face_defer
= 1;
592 /* If F needs to be redrawn, simply forget about any prior mouse
594 if (FRAME_GARBAGED_P (f
))
595 hlinfo
->mouse_face_window
= Qnil
;
602 /* Draw a vertical window border from (x,y0) to (x,y1) */
605 x_draw_vertical_window_border (struct window
*w
, int x
, int y0
, int y1
)
607 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
610 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
612 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
615 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
616 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
619 /* End update of window W (which is equal to updated_window).
621 Draw vertical borders between horizontally adjacent windows, and
622 display W's cursor if CURSOR_ON_P is non-zero.
624 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
625 glyphs in mouse-face were overwritten. In that case we have to
626 make sure that the mouse-highlight is properly redrawn.
628 W may be a menu bar pseudo-window in case we don't have X toolkit
629 support. Such windows don't have a cursor, so don't display it
633 x_update_window_end (struct window
*w
, int cursor_on_p
, int mouse_face_overwritten_p
)
635 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (XFRAME (w
->frame
));
637 if (!w
->pseudo_window_p
)
642 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
644 output_cursor
.x
, output_cursor
.y
);
646 if (draw_window_fringes (w
, 1))
647 x_draw_vertical_border (w
);
652 /* If a row with mouse-face was overwritten, arrange for
653 XTframe_up_to_date to redisplay the mouse highlight. */
654 if (mouse_face_overwritten_p
)
656 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
657 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
658 hlinfo
->mouse_face_window
= Qnil
;
661 updated_window
= NULL
;
665 /* End update of frame F. This function is installed as a hook in
669 x_update_end (struct frame
*f
)
671 /* Mouse highlight may be displayed again. */
672 MOUSE_HL_INFO (f
)->mouse_face_defer
= 0;
676 XFlush (FRAME_X_DISPLAY (f
));
682 /* This function is called from various places in xdisp.c whenever a
683 complete update has been performed. The global variable
684 updated_window is not available here. */
687 XTframe_up_to_date (struct frame
*f
)
691 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (f
);
693 if (hlinfo
->mouse_face_deferred_gc
694 || f
== hlinfo
->mouse_face_mouse_frame
)
697 if (hlinfo
->mouse_face_mouse_frame
)
698 note_mouse_highlight (hlinfo
->mouse_face_mouse_frame
,
699 hlinfo
->mouse_face_mouse_x
,
700 hlinfo
->mouse_face_mouse_y
);
701 hlinfo
->mouse_face_deferred_gc
= 0;
708 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
709 arrow bitmaps, or clear the fringes if no bitmaps are required
710 before DESIRED_ROW is made current. The window being updated is
711 found in updated_window. This function It is called from
712 update_window_line only if it is known that there are differences
713 between bitmaps to be drawn between current row and DESIRED_ROW. */
716 x_after_update_window_line (struct glyph_row
*desired_row
)
718 struct window
*w
= updated_window
;
724 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
725 desired_row
->redraw_fringe_bitmaps_p
= 1;
727 /* When a window has disappeared, make sure that no rest of
728 full-width rows stays visible in the internal border. Could
729 check here if updated_window is the leftmost/rightmost window,
730 but I guess it's not worth doing since vertically split windows
731 are almost never used, internal border is rarely set, and the
732 overhead is very small. */
733 if (windows_or_buffers_changed
734 && desired_row
->full_width_p
735 && (f
= XFRAME (w
->frame
),
736 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
738 && (height
= desired_row
->visible_height
,
741 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
744 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
745 0, y
, width
, height
, False
);
746 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
747 FRAME_PIXEL_WIDTH (f
) - width
,
748 y
, width
, height
, False
);
754 x_draw_fringe_bitmap (struct window
*w
, struct glyph_row
*row
, struct draw_fringe_bitmap_params
*p
)
756 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
757 Display
*display
= FRAME_X_DISPLAY (f
);
758 Window window
= FRAME_X_WINDOW (f
);
759 GC gc
= f
->output_data
.x
->normal_gc
;
760 struct face
*face
= p
->face
;
762 /* Must clip because of partially visible lines. */
763 x_clip_to_row (w
, row
, -1, gc
);
767 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
769 /* In case the same realized face is used for fringes and
770 for something displayed in the text (e.g. face `region' on
771 mono-displays, the fill style may have been changed to
772 FillSolid in x_draw_glyph_string_background. */
774 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
776 XSetForeground (display
, face
->gc
, face
->background
);
778 #ifdef USE_TOOLKIT_SCROLL_BARS
779 /* If the fringe is adjacent to the left (right) scroll bar of a
780 leftmost (rightmost, respectively) window, then extend its
781 background to the gap between the fringe and the bar. */
782 if ((WINDOW_LEFTMOST_P (w
)
783 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
784 || (WINDOW_RIGHTMOST_P (w
)
785 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
787 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
791 int bar_area_x
= WINDOW_SCROLL_BAR_AREA_X (w
);
792 int bar_area_width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
793 * FRAME_COLUMN_WIDTH (f
));
797 /* Bitmap fills the fringe. */
798 if (bar_area_x
+ bar_area_width
== p
->x
)
799 bx
= bar_area_x
+ sb_width
;
800 else if (p
->x
+ p
->wd
== bar_area_x
)
804 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
806 nx
= bar_area_width
- sb_width
;
807 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
809 ny
= row
->visible_height
;
814 if (bar_area_x
+ bar_area_width
== bx
)
816 bx
= bar_area_x
+ sb_width
;
817 nx
+= bar_area_width
- sb_width
;
819 else if (bx
+ nx
== bar_area_x
)
820 nx
+= bar_area_width
- sb_width
;
825 if (bx
>= 0 && nx
> 0)
826 XFillRectangle (display
, window
, face
->gc
, bx
, by
, nx
, ny
);
829 XSetForeground (display
, face
->gc
, face
->foreground
);
835 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
836 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
840 bits
= (char *) (p
->bits
+ p
->dh
);
842 bits
= (char *) p
->bits
+ p
->dh
;
844 /* Draw the bitmap. I believe these small pixmaps can be cached
846 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
848 ? (p
->overlay_p
? face
->background
849 : f
->output_data
.x
->cursor_pixel
)
851 face
->background
, depth
);
855 clipmask
= XCreatePixmapFromBitmapData (display
,
856 FRAME_X_DISPLAY_INFO (f
)->root_window
,
859 gcv
.clip_mask
= clipmask
;
860 gcv
.clip_x_origin
= p
->x
;
861 gcv
.clip_y_origin
= p
->y
;
862 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
865 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
866 p
->wd
, p
->h
, p
->x
, p
->y
);
867 XFreePixmap (display
, pixmap
);
871 gcv
.clip_mask
= (Pixmap
) 0;
872 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
873 XFreePixmap (display
, clipmask
);
877 XSetClipMask (display
, gc
, None
);
882 /* This is called when starting Emacs and when restarting after
883 suspend. When starting Emacs, no X window is mapped. And nothing
884 must be done to Emacs's own window if it is suspended (though that
888 XTset_terminal_modes (struct terminal
*terminal
)
892 /* This is called when exiting or suspending Emacs. Exiting will make
893 the X-windows go away, and suspending requires no action. */
896 XTreset_terminal_modes (struct terminal
*terminal
)
901 /***********************************************************************
903 ***********************************************************************/
907 static void x_set_glyph_string_clipping (struct glyph_string
*);
908 static void x_set_glyph_string_gc (struct glyph_string
*);
909 static void x_draw_glyph_string_background (struct glyph_string
*,
911 static void x_draw_glyph_string_foreground (struct glyph_string
*);
912 static void x_draw_composite_glyph_string_foreground (struct glyph_string
*);
913 static void x_draw_glyph_string_box (struct glyph_string
*);
914 static void x_draw_glyph_string (struct glyph_string
*);
915 static void x_delete_glyphs (struct frame
*, int) NO_RETURN
;
916 static void x_compute_glyph_string_overhangs (struct glyph_string
*);
917 static void x_set_cursor_gc (struct glyph_string
*);
918 static void x_set_mode_line_face_gc (struct glyph_string
*);
919 static void x_set_mouse_face_gc (struct glyph_string
*);
920 static int x_alloc_lighter_color (struct frame
*, Display
*, Colormap
,
921 unsigned long *, double, int);
922 static void x_setup_relief_color (struct frame
*, struct relief
*,
923 double, int, unsigned long);
924 static void x_setup_relief_colors (struct glyph_string
*);
925 static void x_draw_image_glyph_string (struct glyph_string
*);
926 static void x_draw_image_relief (struct glyph_string
*);
927 static void x_draw_image_foreground (struct glyph_string
*);
928 static void x_draw_image_foreground_1 (struct glyph_string
*, Pixmap
);
929 static void x_clear_glyph_string_rect (struct glyph_string
*, int,
931 static void x_draw_relief_rect (struct frame
*, int, int, int, int,
932 int, int, int, int, int, int,
934 static void x_draw_box_rect (struct glyph_string
*, int, int, int, int,
935 int, int, int, XRectangle
*);
936 static void x_scroll_bar_clear (struct frame
*);
939 static void x_check_font (struct frame
*, struct font
*);
943 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
947 x_set_cursor_gc (struct glyph_string
*s
)
949 if (s
->font
== FRAME_FONT (s
->f
)
950 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
951 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
953 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
956 /* Cursor on non-default face: must merge. */
960 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
961 xgcv
.foreground
= s
->face
->background
;
963 /* If the glyph would be invisible, try a different foreground. */
964 if (xgcv
.foreground
== xgcv
.background
)
965 xgcv
.foreground
= s
->face
->foreground
;
966 if (xgcv
.foreground
== xgcv
.background
)
967 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
968 if (xgcv
.foreground
== xgcv
.background
)
969 xgcv
.foreground
= s
->face
->foreground
;
971 /* Make sure the cursor is distinct from text in this face. */
972 if (xgcv
.background
== s
->face
->background
973 && xgcv
.foreground
== s
->face
->foreground
)
975 xgcv
.background
= s
->face
->foreground
;
976 xgcv
.foreground
= s
->face
->background
;
979 IF_DEBUG (x_check_font (s
->f
, s
->font
));
980 xgcv
.graphics_exposures
= False
;
981 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
983 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
984 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
987 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
988 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
990 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
995 /* Set up S->gc of glyph string S for drawing text in mouse face. */
998 x_set_mouse_face_gc (struct glyph_string
*s
)
1003 /* What face has to be used last for the mouse face? */
1004 face_id
= MOUSE_HL_INFO (s
->f
)->mouse_face_face_id
;
1005 face
= FACE_FROM_ID (s
->f
, face_id
);
1007 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1009 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1010 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1012 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1013 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1014 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1016 if (s
->font
== s
->face
->font
)
1017 s
->gc
= s
->face
->gc
;
1020 /* Otherwise construct scratch_cursor_gc with values from FACE
1025 xgcv
.background
= s
->face
->background
;
1026 xgcv
.foreground
= s
->face
->foreground
;
1027 xgcv
.graphics_exposures
= False
;
1028 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
1030 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1031 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1034 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1035 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1037 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1040 xassert (s
->gc
!= 0);
1044 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1045 Faces to use in the mode line have already been computed when the
1046 matrix was built, so there isn't much to do, here. */
1049 x_set_mode_line_face_gc (struct glyph_string
*s
)
1051 s
->gc
= s
->face
->gc
;
1055 /* Set S->gc of glyph string S for drawing that glyph string. Set
1056 S->stippled_p to a non-zero value if the face of S has a stipple
1060 x_set_glyph_string_gc (struct glyph_string
*s
)
1062 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1064 if (s
->hl
== DRAW_NORMAL_TEXT
)
1066 s
->gc
= s
->face
->gc
;
1067 s
->stippled_p
= s
->face
->stipple
!= 0;
1069 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1071 x_set_mode_line_face_gc (s
);
1072 s
->stippled_p
= s
->face
->stipple
!= 0;
1074 else if (s
->hl
== DRAW_CURSOR
)
1076 x_set_cursor_gc (s
);
1079 else if (s
->hl
== DRAW_MOUSE_FACE
)
1081 x_set_mouse_face_gc (s
);
1082 s
->stippled_p
= s
->face
->stipple
!= 0;
1084 else if (s
->hl
== DRAW_IMAGE_RAISED
1085 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1087 s
->gc
= s
->face
->gc
;
1088 s
->stippled_p
= s
->face
->stipple
!= 0;
1092 s
->gc
= s
->face
->gc
;
1093 s
->stippled_p
= s
->face
->stipple
!= 0;
1096 /* GC must have been set. */
1097 xassert (s
->gc
!= 0);
1101 /* Set clipping for output of glyph string S. S may be part of a mode
1102 line or menu if we don't have X toolkit support. */
1105 x_set_glyph_string_clipping (struct glyph_string
*s
)
1107 XRectangle
*r
= s
->clip
;
1108 int n
= get_glyph_string_clip_rects (s
, r
, 2);
1111 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, r
, n
, Unsorted
);
1116 /* Set SRC's clipping for output of glyph string DST. This is called
1117 when we are drawing DST's left_overhang or right_overhang only in
1121 x_set_glyph_string_clipping_exactly (struct glyph_string
*src
, struct glyph_string
*dst
)
1126 r
.width
= src
->width
;
1128 r
.height
= src
->height
;
1131 XSetClipRectangles (dst
->display
, dst
->gc
, 0, 0, &r
, 1, Unsorted
);
1136 Compute left and right overhang of glyph string S. */
1139 x_compute_glyph_string_overhangs (struct glyph_string
*s
)
1142 && (s
->first_glyph
->type
== CHAR_GLYPH
1143 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
1145 struct font_metrics metrics
;
1147 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1149 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1150 struct font
*font
= s
->font
;
1153 for (i
= 0; i
< s
->nchars
; i
++)
1154 code
[i
] = (s
->char2b
[i
].byte1
<< 8) | s
->char2b
[i
].byte2
;
1155 font
->driver
->text_extents (font
, code
, s
->nchars
, &metrics
);
1159 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1161 composition_gstring_width (gstring
, s
->cmp_from
, s
->cmp_to
, &metrics
);
1163 s
->right_overhang
= (metrics
.rbearing
> metrics
.width
1164 ? metrics
.rbearing
- metrics
.width
: 0);
1165 s
->left_overhang
= metrics
.lbearing
< 0 ? - metrics
.lbearing
: 0;
1169 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
1170 s
->left_overhang
= - s
->cmp
->lbearing
;
1175 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1178 x_clear_glyph_string_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
1181 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1182 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1183 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1184 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1188 /* Draw the background of glyph_string S. If S->background_filled_p
1189 is non-zero don't draw it. FORCE_P non-zero means draw the
1190 background even if it wouldn't be drawn normally. This is used
1191 when a string preceding S draws into the background of S, or S
1192 contains the first component of a composition. */
1195 x_draw_glyph_string_background (struct glyph_string
*s
, int force_p
)
1197 /* Nothing to do if background has already been drawn or if it
1198 shouldn't be drawn in the first place. */
1199 if (!s
->background_filled_p
)
1201 int box_line_width
= max (s
->face
->box_line_width
, 0);
1205 /* Fill background with a stipple pattern. */
1206 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1207 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1208 s
->y
+ box_line_width
,
1209 s
->background_width
,
1210 s
->height
- 2 * box_line_width
);
1211 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1212 s
->background_filled_p
= 1;
1214 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1215 || s
->font_not_found_p
1216 || s
->extends_to_end_of_line_p
1219 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1220 s
->background_width
,
1221 s
->height
- 2 * box_line_width
);
1222 s
->background_filled_p
= 1;
1228 /* Draw the foreground of glyph string S. */
1231 x_draw_glyph_string_foreground (struct glyph_string
*s
)
1235 /* If first glyph of S has a left box line, start drawing the text
1236 of S to the right of that box line. */
1237 if (s
->face
->box
!= FACE_NO_BOX
1238 && s
->first_glyph
->left_box_line_p
)
1239 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1243 /* Draw characters of S as rectangles if S's font could not be
1245 if (s
->font_not_found_p
)
1247 for (i
= 0; i
< s
->nchars
; ++i
)
1249 struct glyph
*g
= s
->first_glyph
+ i
;
1250 XDrawRectangle (s
->display
, s
->window
,
1251 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1253 x
+= g
->pixel_width
;
1258 struct font
*font
= s
->font
;
1259 int boff
= font
->baseline_offset
;
1262 if (font
->vertical_centering
)
1263 boff
= VCENTER_BASELINE_OFFSET (font
, s
->f
) - boff
;
1265 y
= s
->ybase
- boff
;
1267 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1268 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 0);
1270 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 1);
1271 if (s
->face
->overstrike
)
1272 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, 0);
1276 /* Draw the foreground of composite glyph string S. */
1279 x_draw_composite_glyph_string_foreground (struct glyph_string
*s
)
1282 struct font
*font
= s
->font
;
1284 /* If first glyph of S has a left box line, start drawing the text
1285 of S to the right of that box line. */
1286 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1287 && s
->first_glyph
->left_box_line_p
)
1288 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1292 /* S is a glyph string for a composition. S->cmp_from is the index
1293 of the first character drawn for glyphs of this composition.
1294 S->cmp_from == 0 means we are drawing the very first character of
1295 this composition. */
1297 /* Draw a rectangle for the composition if the font for the very
1298 first character of the composition could not be loaded. */
1299 if (s
->font_not_found_p
)
1301 if (s
->cmp_from
== 0)
1302 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1303 s
->width
- 1, s
->height
- 1);
1305 else if (! s
->first_glyph
->u
.cmp
.automatic
)
1309 for (i
= 0, j
= s
->cmp_from
; i
< s
->nchars
; i
++, j
++)
1310 /* TAB in a composition means display glyphs with padding
1311 space on the left or right. */
1312 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1314 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1315 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1317 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, 0);
1318 if (s
->face
->overstrike
)
1319 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, 0);
1324 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1329 for (i
= j
= s
->cmp_from
; i
< s
->cmp_to
; i
++)
1331 glyph
= LGSTRING_GLYPH (gstring
, i
);
1332 if (NILP (LGLYPH_ADJUSTMENT (glyph
)))
1333 width
+= LGLYPH_WIDTH (glyph
);
1336 int xoff
, yoff
, wadjust
;
1340 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1341 if (s
->face
->overstrike
)
1342 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, 0);
1345 xoff
= LGLYPH_XOFF (glyph
);
1346 yoff
= LGLYPH_YOFF (glyph
);
1347 wadjust
= LGLYPH_WADJUST (glyph
);
1348 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, 0);
1349 if (s
->face
->overstrike
)
1350 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
+ 1, y
+ yoff
, 0);
1358 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1359 if (s
->face
->overstrike
)
1360 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, 0);
1366 /* Draw the foreground of glyph string S for glyphless characters. */
1369 x_draw_glyphless_glyph_string_foreground (struct glyph_string
*s
)
1371 struct glyph
*glyph
= s
->first_glyph
;
1375 /* If first glyph of S has a left box line, start drawing the text
1376 of S to the right of that box line. */
1377 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1378 && s
->first_glyph
->left_box_line_p
)
1379 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1385 for (i
= 0; i
< s
->nchars
; i
++, glyph
++)
1387 char buf
[7], *str
= NULL
;
1388 int len
= glyph
->u
.glyphless
.len
;
1390 if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
)
1393 && CHAR_TABLE_P (Vglyphless_char_display
)
1394 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display
))
1398 = (! glyph
->u
.glyphless
.for_no_font
1399 ? CHAR_TABLE_REF (Vglyphless_char_display
,
1400 glyph
->u
.glyphless
.ch
)
1401 : XCHAR_TABLE (Vglyphless_char_display
)->extras
[0]);
1402 if (STRINGP (acronym
))
1403 str
= SSDATA (acronym
);
1406 else if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
)
1408 sprintf ((char *) buf
, "%0*X",
1409 glyph
->u
.glyphless
.ch
< 0x10000 ? 4 : 6,
1410 glyph
->u
.glyphless
.ch
);
1416 int upper_len
= (len
+ 1) / 2;
1419 /* It is assured that all LEN characters in STR is ASCII. */
1420 for (j
= 0; j
< len
; j
++)
1422 code
= s
->font
->driver
->encode_char (s
->font
, str
[j
]);
1423 STORE_XCHAR2B (char2b
+ j
, code
>> 8, code
& 0xFF);
1425 s
->font
->driver
->draw (s
, 0, upper_len
,
1426 x
+ glyph
->slice
.glyphless
.upper_xoff
,
1427 s
->ybase
+ glyph
->slice
.glyphless
.upper_yoff
,
1429 s
->font
->driver
->draw (s
, upper_len
, len
,
1430 x
+ glyph
->slice
.glyphless
.lower_xoff
,
1431 s
->ybase
+ glyph
->slice
.glyphless
.lower_yoff
,
1434 if (glyph
->u
.glyphless
.method
!= GLYPHLESS_DISPLAY_THIN_SPACE
)
1435 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
1436 x
, s
->ybase
- glyph
->ascent
,
1437 glyph
->pixel_width
- 1,
1438 glyph
->ascent
+ glyph
->descent
- 1);
1439 x
+= glyph
->pixel_width
;
1443 #ifdef USE_X_TOOLKIT
1445 static struct frame
*x_frame_of_widget (Widget
);
1446 static Boolean
cvt_string_to_pixel (Display
*, XrmValue
*, Cardinal
*,
1447 XrmValue
*, XrmValue
*, XtPointer
*);
1448 static void cvt_pixel_dtor (XtAppContext
, XrmValue
*, XtPointer
,
1449 XrmValue
*, Cardinal
*);
1452 /* Return the frame on which widget WIDGET is used.. Abort if frame
1453 cannot be determined. */
1455 static struct frame
*
1456 x_frame_of_widget (Widget widget
)
1458 struct x_display_info
*dpyinfo
;
1462 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1464 /* Find the top-level shell of the widget. Note that this function
1465 can be called when the widget is not yet realized, so XtWindow
1466 (widget) == 0. That's the reason we can't simply use
1467 x_any_window_to_frame. */
1468 while (!XtIsTopLevelShell (widget
))
1469 widget
= XtParent (widget
);
1471 /* Look for a frame with that top-level widget. Allocate the color
1472 on that frame to get the right gamma correction value. */
1473 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1474 if (FRAMEP (XCAR (tail
))
1475 && (f
= XFRAME (XCAR (tail
)),
1477 && f
->output_data
.nothing
!= 1
1478 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
1479 && f
->output_data
.x
->widget
== widget
)
1488 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1489 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1490 If this produces the same color as PIXEL, try a color where all RGB
1491 values have DELTA added. Return the allocated color in *PIXEL.
1492 DISPLAY is the X display, CMAP is the colormap to operate on.
1493 Value is non-zero if successful. */
1496 x_alloc_lighter_color_for_widget (Widget widget
, Display
*display
, Colormap cmap
,
1497 unsigned long *pixel
, double factor
, int delta
)
1499 struct frame
*f
= x_frame_of_widget (widget
);
1500 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1506 /* Structure specifying which arguments should be passed by Xt to
1507 cvt_string_to_pixel. We want the widget's screen and colormap. */
1509 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1511 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1513 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1518 /* The address of this variable is returned by
1519 cvt_string_to_pixel. */
1521 static Pixel cvt_string_to_pixel_value
;
1524 /* Convert a color name to a pixel color.
1526 DPY is the display we are working on.
1528 ARGS is an array of *NARGS XrmValue structures holding additional
1529 information about the widget for which the conversion takes place.
1530 The contents of this array are determined by the specification
1531 in cvt_string_to_pixel_args.
1533 FROM is a pointer to an XrmValue which points to the color name to
1534 convert. TO is an XrmValue in which to return the pixel color.
1536 CLOSURE_RET is a pointer to user-data, in which we record if
1537 we allocated the color or not.
1539 Value is True if successful, False otherwise. */
1542 cvt_string_to_pixel (Display
*dpy
, XrmValue
*args
, Cardinal
*nargs
,
1543 XrmValue
*from
, XrmValue
*to
,
1544 XtPointer
*closure_ret
)
1554 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1555 "wrongParameters", "cvt_string_to_pixel",
1557 "Screen and colormap args required", NULL
, NULL
);
1561 screen
= *(Screen
**) args
[0].addr
;
1562 cmap
= *(Colormap
*) args
[1].addr
;
1563 color_name
= (String
) from
->addr
;
1565 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1567 *closure_ret
= (XtPointer
) False
;
1568 pixel
= WhitePixelOfScreen (screen
);
1570 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1572 *closure_ret
= (XtPointer
) False
;
1573 pixel
= BlackPixelOfScreen (screen
);
1575 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1576 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1578 pixel
= color
.pixel
;
1579 *closure_ret
= (XtPointer
) True
;
1584 Cardinal nparams
= 1;
1586 params
[0] = color_name
;
1587 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1588 "badValue", "cvt_string_to_pixel",
1589 "XtToolkitError", "Invalid color `%s'",
1594 if (to
->addr
!= NULL
)
1596 if (to
->size
< sizeof (Pixel
))
1598 to
->size
= sizeof (Pixel
);
1602 *(Pixel
*) to
->addr
= pixel
;
1606 cvt_string_to_pixel_value
= pixel
;
1607 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1610 to
->size
= sizeof (Pixel
);
1615 /* Free a pixel color which was previously allocated via
1616 cvt_string_to_pixel. This is registered as the destructor
1617 for this type of resource via XtSetTypeConverter.
1619 APP is the application context in which we work.
1621 TO is a pointer to an XrmValue holding the color to free.
1622 CLOSURE is the value we stored in CLOSURE_RET for this color
1623 in cvt_string_to_pixel.
1625 ARGS and NARGS are like for cvt_string_to_pixel. */
1628 cvt_pixel_dtor (XtAppContext app
, XrmValuePtr to
, XtPointer closure
, XrmValuePtr args
,
1633 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1635 "Screen and colormap arguments required",
1638 else if (closure
!= NULL
)
1640 /* We did allocate the pixel, so free it. */
1641 Screen
*screen
= *(Screen
**) args
[0].addr
;
1642 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1643 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1644 (Pixel
*) to
->addr
, 1);
1649 #endif /* USE_X_TOOLKIT */
1652 /* Value is an array of XColor structures for the contents of the
1653 color map of display DPY. Set *NCELLS to the size of the array.
1654 Note that this probably shouldn't be called for large color maps,
1655 say a 24-bit TrueColor map. */
1657 static const XColor
*
1658 x_color_cells (Display
*dpy
, int *ncells
)
1660 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1662 if (dpyinfo
->color_cells
== NULL
)
1664 Screen
*screen
= dpyinfo
->screen
;
1665 int ncolor_cells
= XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1668 dpyinfo
->color_cells
= xnmalloc (ncolor_cells
,
1669 sizeof *dpyinfo
->color_cells
);
1670 dpyinfo
->ncolor_cells
= ncolor_cells
;
1672 for (i
= 0; i
< ncolor_cells
; ++i
)
1673 dpyinfo
->color_cells
[i
].pixel
= i
;
1675 XQueryColors (dpy
, dpyinfo
->cmap
,
1676 dpyinfo
->color_cells
, ncolor_cells
);
1679 *ncells
= dpyinfo
->ncolor_cells
;
1680 return dpyinfo
->color_cells
;
1684 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1685 colors in COLORS. Use cached information, if available. */
1688 x_query_colors (struct frame
*f
, XColor
*colors
, int ncolors
)
1690 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1692 if (dpyinfo
->color_cells
)
1695 for (i
= 0; i
< ncolors
; ++i
)
1697 unsigned long pixel
= colors
[i
].pixel
;
1698 xassert (pixel
< dpyinfo
->ncolor_cells
);
1699 xassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1700 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1704 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1708 /* On frame F, translate pixel color to RGB values for the color in
1709 COLOR. Use cached information, if available. */
1712 x_query_color (struct frame
*f
, XColor
*color
)
1714 x_query_colors (f
, color
, 1);
1718 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1719 exact match can't be allocated, try the nearest color available.
1720 Value is non-zero if successful. Set *COLOR to the color
1724 x_alloc_nearest_color_1 (Display
*dpy
, Colormap cmap
, XColor
*color
)
1728 rc
= XAllocColor (dpy
, cmap
, color
);
1731 /* If we got to this point, the colormap is full, so we're going
1732 to try to get the next closest color. The algorithm used is
1733 a least-squares matching, which is what X uses for closest
1734 color matching with StaticColor visuals. */
1736 int max_color_delta
= 255;
1737 int max_delta
= 3 * max_color_delta
;
1738 int nearest_delta
= max_delta
+ 1;
1740 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1742 for (nearest
= i
= 0; i
< ncells
; ++i
)
1744 int dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1745 int dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1746 int dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1747 int delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1749 if (delta
< nearest_delta
)
1752 nearest_delta
= delta
;
1756 color
->red
= cells
[nearest
].red
;
1757 color
->green
= cells
[nearest
].green
;
1758 color
->blue
= cells
[nearest
].blue
;
1759 rc
= XAllocColor (dpy
, cmap
, color
);
1763 /* If allocation succeeded, and the allocated pixel color is not
1764 equal to a cached pixel color recorded earlier, there was a
1765 change in the colormap, so clear the color cache. */
1766 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1767 XColor
*cached_color
;
1769 if (dpyinfo
->color_cells
1770 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1771 (cached_color
->red
!= color
->red
1772 || cached_color
->blue
!= color
->blue
1773 || cached_color
->green
!= color
->green
)))
1775 xfree (dpyinfo
->color_cells
);
1776 dpyinfo
->color_cells
= NULL
;
1777 dpyinfo
->ncolor_cells
= 0;
1781 #ifdef DEBUG_X_COLORS
1783 register_color (color
->pixel
);
1784 #endif /* DEBUG_X_COLORS */
1790 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1791 exact match can't be allocated, try the nearest color available.
1792 Value is non-zero if successful. Set *COLOR to the color
1796 x_alloc_nearest_color (struct frame
*f
, Colormap cmap
, XColor
*color
)
1798 gamma_correct (f
, color
);
1799 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1803 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1804 It's necessary to do this instead of just using PIXEL directly to
1805 get color reference counts right. */
1808 x_copy_color (struct frame
*f
, long unsigned int pixel
)
1812 color
.pixel
= pixel
;
1814 x_query_color (f
, &color
);
1815 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1817 #ifdef DEBUG_X_COLORS
1818 register_color (pixel
);
1824 /* Brightness beyond which a color won't have its highlight brightness
1827 Nominally, highlight colors for `3d' faces are calculated by
1828 brightening an object's color by a constant scale factor, but this
1829 doesn't yield good results for dark colors, so for colors who's
1830 brightness is less than this value (on a scale of 0-65535) have an
1831 use an additional additive factor.
1833 The value here is set so that the default menu-bar/mode-line color
1834 (grey75) will not have its highlights changed at all. */
1835 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1838 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1839 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1840 If this produces the same color as PIXEL, try a color where all RGB
1841 values have DELTA added. Return the allocated color in *PIXEL.
1842 DISPLAY is the X display, CMAP is the colormap to operate on.
1843 Value is non-zero if successful. */
1846 x_alloc_lighter_color (struct frame
*f
, Display
*display
, Colormap cmap
, long unsigned int *pixel
, double factor
, int delta
)
1852 /* Get RGB color values. */
1853 color
.pixel
= *pixel
;
1854 x_query_color (f
, &color
);
1856 /* Change RGB values by specified FACTOR. Avoid overflow! */
1857 xassert (factor
>= 0);
1858 new.red
= min (0xffff, factor
* color
.red
);
1859 new.green
= min (0xffff, factor
* color
.green
);
1860 new.blue
= min (0xffff, factor
* color
.blue
);
1862 /* Calculate brightness of COLOR. */
1863 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
1865 /* We only boost colors that are darker than
1866 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1867 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1868 /* Make an additive adjustment to NEW, because it's dark enough so
1869 that scaling by FACTOR alone isn't enough. */
1871 /* How far below the limit this color is (0 - 1, 1 being darker). */
1872 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1873 /* The additive adjustment. */
1874 int min_delta
= delta
* dimness
* factor
/ 2;
1878 new.red
= max (0, new.red
- min_delta
);
1879 new.green
= max (0, new.green
- min_delta
);
1880 new.blue
= max (0, new.blue
- min_delta
);
1884 new.red
= min (0xffff, min_delta
+ new.red
);
1885 new.green
= min (0xffff, min_delta
+ new.green
);
1886 new.blue
= min (0xffff, min_delta
+ new.blue
);
1890 /* Try to allocate the color. */
1891 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1894 if (new.pixel
== *pixel
)
1896 /* If we end up with the same color as before, try adding
1897 delta to the RGB values. */
1898 x_free_colors (f
, &new.pixel
, 1);
1900 new.red
= min (0xffff, delta
+ color
.red
);
1901 new.green
= min (0xffff, delta
+ color
.green
);
1902 new.blue
= min (0xffff, delta
+ color
.blue
);
1903 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1914 /* Set up the foreground color for drawing relief lines of glyph
1915 string S. RELIEF is a pointer to a struct relief containing the GC
1916 with which lines will be drawn. Use a color that is FACTOR or
1917 DELTA lighter or darker than the relief's background which is found
1918 in S->f->output_data.x->relief_background. If such a color cannot
1919 be allocated, use DEFAULT_PIXEL, instead. */
1922 x_setup_relief_color (struct frame
*f
, struct relief
*relief
, double factor
, int delta
, long unsigned int default_pixel
)
1925 struct x_output
*di
= f
->output_data
.x
;
1926 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
1927 unsigned long pixel
;
1928 unsigned long background
= di
->relief_background
;
1929 Colormap cmap
= FRAME_X_COLORMAP (f
);
1930 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1931 Display
*dpy
= FRAME_X_DISPLAY (f
);
1933 xgcv
.graphics_exposures
= False
;
1934 xgcv
.line_width
= 1;
1936 /* Free previously allocated color. The color cell will be reused
1937 when it has been freed as many times as it was allocated, so this
1938 doesn't affect faces using the same colors. */
1940 && relief
->allocated_p
)
1942 x_free_colors (f
, &relief
->pixel
, 1);
1943 relief
->allocated_p
= 0;
1946 /* Allocate new color. */
1947 xgcv
.foreground
= default_pixel
;
1949 if (dpyinfo
->n_planes
!= 1
1950 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
1952 relief
->allocated_p
= 1;
1953 xgcv
.foreground
= relief
->pixel
= pixel
;
1956 if (relief
->gc
== 0)
1958 xgcv
.stipple
= dpyinfo
->gray
;
1960 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
1963 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
1967 /* Set up colors for the relief lines around glyph string S. */
1970 x_setup_relief_colors (struct glyph_string
*s
)
1972 struct x_output
*di
= s
->f
->output_data
.x
;
1973 unsigned long color
;
1975 if (s
->face
->use_box_color_for_shadows_p
)
1976 color
= s
->face
->box_color
;
1977 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1979 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1980 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1985 /* Get the background color of the face. */
1986 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
1987 color
= xgcv
.background
;
1990 if (di
->white_relief
.gc
== 0
1991 || color
!= di
->relief_background
)
1993 di
->relief_background
= color
;
1994 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1995 WHITE_PIX_DEFAULT (s
->f
));
1996 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1997 BLACK_PIX_DEFAULT (s
->f
));
2002 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2003 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2004 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2005 relief. LEFT_P non-zero means draw a relief on the left side of
2006 the rectangle. RIGHT_P non-zero means draw a relief on the right
2007 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2011 x_draw_relief_rect (struct frame
*f
,
2012 int left_x
, int top_y
, int right_x
, int bottom_y
, int width
,
2013 int raised_p
, int top_p
, int bot_p
, int left_p
, int right_p
,
2014 XRectangle
*clip_rect
)
2016 Display
*dpy
= FRAME_X_DISPLAY (f
);
2017 Window window
= FRAME_X_WINDOW (f
);
2022 gc
= f
->output_data
.x
->white_relief
.gc
;
2024 gc
= f
->output_data
.x
->black_relief
.gc
;
2025 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2027 /* This code is more complicated than it has to be, because of two
2028 minor hacks to make the boxes look nicer: (i) if width > 1, draw
2029 the outermost line using the black relief. (ii) Omit the four
2036 XDrawLine (dpy
, window
, gc
,
2037 left_x
+ (left_p
? 1 : 0), top_y
,
2038 right_x
+ (right_p
? 0 : 1), top_y
);
2040 for (i
= 1; i
< width
; ++i
)
2041 XDrawLine (dpy
, window
, gc
,
2042 left_x
+ i
* left_p
, top_y
+ i
,
2043 right_x
+ 1 - i
* right_p
, top_y
+ i
);
2050 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
2052 XClearArea (dpy
, window
, left_x
, top_y
, 1, 1, False
);
2053 XClearArea (dpy
, window
, left_x
, bottom_y
, 1, 1, False
);
2055 for (i
= (width
> 1 ? 1 : 0); i
< width
; ++i
)
2056 XDrawLine (dpy
, window
, gc
,
2057 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
+ 1);
2060 XSetClipMask (dpy
, gc
, None
);
2062 gc
= f
->output_data
.x
->black_relief
.gc
;
2064 gc
= f
->output_data
.x
->white_relief
.gc
;
2065 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
2069 /* Outermost top line. */
2071 XDrawLine (dpy
, window
, gc
,
2072 left_x
+ (left_p
? 1 : 0), top_y
,
2073 right_x
+ (right_p
? 0 : 1), top_y
);
2075 /* Outermost left line. */
2077 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
2083 XDrawLine (dpy
, window
, gc
,
2084 left_x
+ (left_p
? 1 : 0), bottom_y
,
2085 right_x
+ (right_p
? 0 : 1), bottom_y
);
2086 for (i
= 1; i
< width
; ++i
)
2087 XDrawLine (dpy
, window
, gc
,
2088 left_x
+ i
* left_p
, bottom_y
- i
,
2089 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
2095 XClearArea (dpy
, window
, right_x
, top_y
, 1, 1, False
);
2096 XClearArea (dpy
, window
, right_x
, bottom_y
, 1, 1, False
);
2097 for (i
= 0; i
< width
; ++i
)
2098 XDrawLine (dpy
, window
, gc
,
2099 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
2102 XSetClipMask (dpy
, gc
, None
);
2106 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2107 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2108 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2109 left side of the rectangle. RIGHT_P non-zero means draw a line
2110 on the right side of the rectangle. CLIP_RECT is the clipping
2111 rectangle to use when drawing. */
2114 x_draw_box_rect (struct glyph_string
*s
,
2115 int left_x
, int top_y
, int right_x
, int bottom_y
, int width
,
2116 int left_p
, int right_p
, XRectangle
*clip_rect
)
2120 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2121 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2122 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2125 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2126 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2130 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2131 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2134 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2135 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2139 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2140 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2142 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2143 XSetClipMask (s
->display
, s
->gc
, None
);
2147 /* Draw a box around glyph string S. */
2150 x_draw_glyph_string_box (struct glyph_string
*s
)
2152 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2153 int left_p
, right_p
;
2154 struct glyph
*last_glyph
;
2155 XRectangle clip_rect
;
2157 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2158 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2159 : window_box_right (s
->w
, s
->area
));
2161 /* The glyph that may have a right box line. */
2162 last_glyph
= (s
->cmp
|| s
->img
2164 : s
->first_glyph
+ s
->nchars
- 1);
2166 width
= eabs (s
->face
->box_line_width
);
2167 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2169 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2171 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2173 bottom_y
= top_y
+ s
->height
- 1;
2175 left_p
= (s
->first_glyph
->left_box_line_p
2176 || (s
->hl
== DRAW_MOUSE_FACE
2178 || s
->prev
->hl
!= s
->hl
)));
2179 right_p
= (last_glyph
->right_box_line_p
2180 || (s
->hl
== DRAW_MOUSE_FACE
2182 || s
->next
->hl
!= s
->hl
)));
2184 get_glyph_string_clip_rect (s
, &clip_rect
);
2186 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2187 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2188 left_p
, right_p
, &clip_rect
);
2191 x_setup_relief_colors (s
);
2192 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2193 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2198 /* Draw foreground of image glyph string S. */
2201 x_draw_image_foreground (struct glyph_string
*s
)
2204 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2206 /* If first glyph of S has a left box line, start drawing it to the
2207 right of that line. */
2208 if (s
->face
->box
!= FACE_NO_BOX
2209 && s
->first_glyph
->left_box_line_p
2211 x
+= eabs (s
->face
->box_line_width
);
2213 /* If there is a margin around the image, adjust x- and y-position
2215 if (s
->slice
.x
== 0)
2216 x
+= s
->img
->hmargin
;
2217 if (s
->slice
.y
== 0)
2218 y
+= s
->img
->vmargin
;
2224 /* We can't set both a clip mask and use XSetClipRectangles
2225 because the latter also sets a clip mask. We also can't
2226 trust on the shape extension to be available
2227 (XShapeCombineRegion). So, compute the rectangle to draw
2229 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2232 XRectangle clip_rect
, image_rect
, r
;
2234 xgcv
.clip_mask
= s
->img
->mask
;
2235 xgcv
.clip_x_origin
= x
;
2236 xgcv
.clip_y_origin
= y
;
2237 xgcv
.function
= GXcopy
;
2238 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2240 get_glyph_string_clip_rect (s
, &clip_rect
);
2243 image_rect
.width
= s
->slice
.width
;
2244 image_rect
.height
= s
->slice
.height
;
2245 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2246 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2247 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2248 r
.width
, r
.height
, r
.x
, r
.y
);
2252 XRectangle clip_rect
, image_rect
, r
;
2254 get_glyph_string_clip_rect (s
, &clip_rect
);
2257 image_rect
.width
= s
->slice
.width
;
2258 image_rect
.height
= s
->slice
.height
;
2259 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2260 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2261 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2262 r
.width
, r
.height
, r
.x
, r
.y
);
2264 /* When the image has a mask, we can expect that at
2265 least part of a mouse highlight or a block cursor will
2266 be visible. If the image doesn't have a mask, make
2267 a block cursor visible by drawing a rectangle around
2268 the image. I believe it's looking better if we do
2269 nothing here for mouse-face. */
2270 if (s
->hl
== DRAW_CURSOR
)
2272 int relief
= s
->img
->relief
;
2273 if (relief
< 0) relief
= -relief
;
2274 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
2275 x
- relief
, y
- relief
,
2276 s
->slice
.width
+ relief
*2 - 1,
2277 s
->slice
.height
+ relief
*2 - 1);
2282 /* Draw a rectangle if image could not be loaded. */
2283 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2284 s
->slice
.width
- 1, s
->slice
.height
- 1);
2288 /* Draw a relief around the image glyph string S. */
2291 x_draw_image_relief (struct glyph_string
*s
)
2293 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2294 int extra_x
, extra_y
;
2297 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2299 /* If first glyph of S has a left box line, start drawing it to the
2300 right of that line. */
2301 if (s
->face
->box
!= FACE_NO_BOX
2302 && s
->first_glyph
->left_box_line_p
2304 x
+= eabs (s
->face
->box_line_width
);
2306 /* If there is a margin around the image, adjust x- and y-position
2308 if (s
->slice
.x
== 0)
2309 x
+= s
->img
->hmargin
;
2310 if (s
->slice
.y
== 0)
2311 y
+= s
->img
->vmargin
;
2313 if (s
->hl
== DRAW_IMAGE_SUNKEN
2314 || s
->hl
== DRAW_IMAGE_RAISED
)
2316 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2317 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2321 thick
= eabs (s
->img
->relief
);
2322 raised_p
= s
->img
->relief
> 0;
2325 extra_x
= extra_y
= 0;
2326 if (s
->face
->id
== TOOL_BAR_FACE_ID
)
2328 if (CONSP (Vtool_bar_button_margin
)
2329 && INTEGERP (XCAR (Vtool_bar_button_margin
))
2330 && INTEGERP (XCDR (Vtool_bar_button_margin
)))
2332 extra_x
= XINT (XCAR (Vtool_bar_button_margin
));
2333 extra_y
= XINT (XCDR (Vtool_bar_button_margin
));
2335 else if (INTEGERP (Vtool_bar_button_margin
))
2336 extra_x
= extra_y
= XINT (Vtool_bar_button_margin
);
2339 x0
= x
- thick
- extra_x
;
2340 y0
= y
- thick
- extra_y
;
2341 x1
= x
+ s
->slice
.width
+ thick
- 1 + extra_x
;
2342 y1
= y
+ s
->slice
.height
+ thick
- 1 + extra_y
;
2344 x_setup_relief_colors (s
);
2345 get_glyph_string_clip_rect (s
, &r
);
2346 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2348 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2350 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2355 /* Draw the foreground of image glyph string S to PIXMAP. */
2358 x_draw_image_foreground_1 (struct glyph_string
*s
, Pixmap pixmap
)
2361 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2363 /* If first glyph of S has a left box line, start drawing it to the
2364 right of that line. */
2365 if (s
->face
->box
!= FACE_NO_BOX
2366 && s
->first_glyph
->left_box_line_p
2368 x
+= eabs (s
->face
->box_line_width
);
2370 /* If there is a margin around the image, adjust x- and y-position
2372 if (s
->slice
.x
== 0)
2373 x
+= s
->img
->hmargin
;
2374 if (s
->slice
.y
== 0)
2375 y
+= s
->img
->vmargin
;
2381 /* We can't set both a clip mask and use XSetClipRectangles
2382 because the latter also sets a clip mask. We also can't
2383 trust on the shape extension to be available
2384 (XShapeCombineRegion). So, compute the rectangle to draw
2386 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2390 xgcv
.clip_mask
= s
->img
->mask
;
2391 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
2392 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
2393 xgcv
.function
= GXcopy
;
2394 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2396 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2397 s
->slice
.x
, s
->slice
.y
,
2398 s
->slice
.width
, s
->slice
.height
, x
, y
);
2399 XSetClipMask (s
->display
, s
->gc
, None
);
2403 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2404 s
->slice
.x
, s
->slice
.y
,
2405 s
->slice
.width
, s
->slice
.height
, x
, y
);
2407 /* When the image has a mask, we can expect that at
2408 least part of a mouse highlight or a block cursor will
2409 be visible. If the image doesn't have a mask, make
2410 a block cursor visible by drawing a rectangle around
2411 the image. I believe it's looking better if we do
2412 nothing here for mouse-face. */
2413 if (s
->hl
== DRAW_CURSOR
)
2415 int r
= s
->img
->relief
;
2417 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2418 s
->slice
.width
+ r
*2 - 1,
2419 s
->slice
.height
+ r
*2 - 1);
2424 /* Draw a rectangle if image could not be loaded. */
2425 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2426 s
->slice
.width
- 1, s
->slice
.height
- 1);
2430 /* Draw part of the background of glyph string S. X, Y, W, and H
2431 give the rectangle to draw. */
2434 x_draw_glyph_string_bg_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
2438 /* Fill background with a stipple pattern. */
2439 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2440 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2441 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2444 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2448 /* Draw image glyph string S.
2451 s->x +-------------------------
2454 | +-------------------------
2457 | | +-------------------
2463 x_draw_image_glyph_string (struct glyph_string
*s
)
2465 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
2466 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2468 Pixmap pixmap
= None
;
2471 if (s
->slice
.y
== 0)
2472 height
-= box_line_vwidth
;
2473 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
2474 height
-= box_line_vwidth
;
2476 /* Fill background with face under the image. Do it only if row is
2477 taller than image or if image has a clip mask to reduce
2479 s
->stippled_p
= s
->face
->stipple
!= 0;
2480 if (height
> s
->slice
.height
2484 || s
->img
->pixmap
== 0
2485 || s
->width
!= s
->background_width
)
2489 /* Create a pixmap as large as the glyph string. Fill it
2490 with the background color. Copy the image to it, using
2491 its mask. Copy the temporary pixmap to the display. */
2492 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2493 int depth
= DefaultDepthOfScreen (screen
);
2495 /* Create a pixmap as large as the glyph string. */
2496 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2497 s
->background_width
,
2500 /* Don't clip in the following because we're working on the
2502 XSetClipMask (s
->display
, s
->gc
, None
);
2504 /* Fill the pixmap with the background color/stipple. */
2507 /* Fill background with a stipple pattern. */
2508 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2509 XSetTSOrigin (s
->display
, s
->gc
, - s
->x
, - s
->y
);
2510 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2511 0, 0, s
->background_width
, s
->height
);
2512 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2513 XSetTSOrigin (s
->display
, s
->gc
, 0, 0);
2518 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2520 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2521 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2522 0, 0, s
->background_width
, s
->height
);
2523 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2531 if (s
->first_glyph
->left_box_line_p
2533 x
+= box_line_hwidth
;
2535 if (s
->slice
.y
== 0)
2536 y
+= box_line_vwidth
;
2538 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2541 s
->background_filled_p
= 1;
2544 /* Draw the foreground. */
2547 x_draw_image_foreground_1 (s
, pixmap
);
2548 x_set_glyph_string_clipping (s
);
2549 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2550 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2551 XFreePixmap (s
->display
, pixmap
);
2554 x_draw_image_foreground (s
);
2556 /* If we must draw a relief around the image, do it. */
2558 || s
->hl
== DRAW_IMAGE_RAISED
2559 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2560 x_draw_image_relief (s
);
2564 /* Draw stretch glyph string S. */
2567 x_draw_stretch_glyph_string (struct glyph_string
*s
)
2569 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2571 if (s
->hl
== DRAW_CURSOR
2572 && !x_stretch_cursor_p
)
2574 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2575 wide as the stretch glyph. */
2576 int width
, background_width
= s
->background_width
;
2579 if (!s
->row
->reversed_p
)
2581 int left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2585 background_width
-= left_x
- x
;
2591 /* In R2L rows, draw the cursor on the right edge of the
2593 int right_x
= window_box_right_offset (s
->w
, TEXT_AREA
);
2595 if (x
+ background_width
> right_x
)
2596 background_width
-= x
- right_x
;
2597 x
+= background_width
;
2599 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
2600 if (s
->row
->reversed_p
)
2604 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
2606 /* Clear rest using the GC of the original non-cursor face. */
2607 if (width
< background_width
)
2610 int w
= background_width
- width
, h
= s
->height
;
2614 if (!s
->row
->reversed_p
)
2618 if (s
->row
->mouse_face_p
2619 && cursor_in_mouse_face_p (s
->w
))
2621 x_set_mouse_face_gc (s
);
2627 get_glyph_string_clip_rect (s
, &r
);
2628 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2630 if (s
->face
->stipple
)
2632 /* Fill background with a stipple pattern. */
2633 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2634 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2635 XSetFillStyle (s
->display
, gc
, FillSolid
);
2640 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2641 XSetForeground (s
->display
, gc
, xgcv
.background
);
2642 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2643 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2647 else if (!s
->background_filled_p
)
2649 int background_width
= s
->background_width
;
2650 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2652 /* Don't draw into left margin, fringe or scrollbar area
2653 except for header line and mode line. */
2654 if (x
< left_x
&& !s
->row
->mode_line_p
)
2656 background_width
-= left_x
- x
;
2659 if (background_width
> 0)
2660 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
2663 s
->background_filled_p
= 1;
2667 Draw a wavy line under S. The wave fills wave_height pixels from y0.
2673 wave_height = 3 | * * * *
2678 x_draw_underwave (struct glyph_string
*s
)
2680 int wave_height
= 2, wave_length
= 3;
2681 int dx
, dy
, x0
, y0
, width
, x1
, y1
, x2
, y2
, odd
, xmax
;
2682 XRectangle wave_clip
, string_clip
, final_clip
;
2685 dy
= wave_height
- 1;
2691 /* Find and set clipping rectangle */
2693 wave_clip
= (XRectangle
){ x0
, y0
, width
, wave_height
};
2694 get_glyph_string_clip_rect (s
, &string_clip
);
2696 if (!x_intersect_rectangles (&wave_clip
, &string_clip
, &final_clip
))
2699 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &final_clip
, 1, Unsorted
);
2701 /* Draw the waves */
2703 x1
= x0
- (x0
% dx
);
2713 if (INT_MAX
- dx
< xmax
)
2718 XDrawLine (s
->display
, s
->window
, s
->gc
, x1
, y1
, x2
, y2
);
2720 x2
+= dx
, y2
= y0
+ odd
*dy
;
2724 /* Restore previous clipping rectangle(s) */
2725 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, s
->clip
, s
->num_clips
, Unsorted
);
2729 /* Draw glyph string S. */
2732 x_draw_glyph_string (struct glyph_string
*s
)
2734 int relief_drawn_p
= 0;
2736 /* If S draws into the background of its successors, draw the
2737 background of the successors first so that S can draw into it.
2738 This makes S->next use XDrawString instead of XDrawImageString. */
2739 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
2742 struct glyph_string
*next
;
2744 for (width
= 0, next
= s
->next
;
2745 next
&& width
< s
->right_overhang
;
2746 width
+= next
->width
, next
= next
->next
)
2747 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
2749 x_set_glyph_string_gc (next
);
2750 x_set_glyph_string_clipping (next
);
2751 if (next
->first_glyph
->type
== STRETCH_GLYPH
)
2752 x_draw_stretch_glyph_string (next
);
2754 x_draw_glyph_string_background (next
, 1);
2755 next
->num_clips
= 0;
2759 /* Set up S->gc, set clipping and draw S. */
2760 x_set_glyph_string_gc (s
);
2762 /* Draw relief (if any) in advance for char/composition so that the
2763 glyph string can be drawn over it. */
2764 if (!s
->for_overlaps
2765 && s
->face
->box
!= FACE_NO_BOX
2766 && (s
->first_glyph
->type
== CHAR_GLYPH
2767 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2770 x_set_glyph_string_clipping (s
);
2771 x_draw_glyph_string_background (s
, 1);
2772 x_draw_glyph_string_box (s
);
2773 x_set_glyph_string_clipping (s
);
2776 else if (!s
->clip_head
/* draw_glyphs didn't specify a clip mask. */
2778 && ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
2779 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
)))
2780 /* We must clip just this glyph. left_overhang part has already
2781 drawn when s->prev was drawn, and right_overhang part will be
2782 drawn later when s->next is drawn. */
2783 x_set_glyph_string_clipping_exactly (s
, s
);
2785 x_set_glyph_string_clipping (s
);
2787 switch (s
->first_glyph
->type
)
2790 x_draw_image_glyph_string (s
);
2794 x_draw_stretch_glyph_string (s
);
2798 if (s
->for_overlaps
)
2799 s
->background_filled_p
= 1;
2801 x_draw_glyph_string_background (s
, 0);
2802 x_draw_glyph_string_foreground (s
);
2805 case COMPOSITE_GLYPH
:
2806 if (s
->for_overlaps
|| (s
->cmp_from
> 0
2807 && ! s
->first_glyph
->u
.cmp
.automatic
))
2808 s
->background_filled_p
= 1;
2810 x_draw_glyph_string_background (s
, 1);
2811 x_draw_composite_glyph_string_foreground (s
);
2814 case GLYPHLESS_GLYPH
:
2815 if (s
->for_overlaps
)
2816 s
->background_filled_p
= 1;
2818 x_draw_glyph_string_background (s
, 1);
2819 x_draw_glyphless_glyph_string_foreground (s
);
2826 if (!s
->for_overlaps
)
2828 /* Draw underline. */
2829 if (s
->face
->underline_p
)
2831 if (s
->face
->underline_type
== FACE_UNDER_WAVE
)
2833 if (s
->face
->underline_defaulted_p
)
2834 x_draw_underwave (s
);
2838 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2839 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2840 x_draw_underwave (s
);
2841 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2844 else if (s
->face
->underline_type
== FACE_UNDER_LINE
)
2846 unsigned long thickness
, position
;
2849 if (s
->prev
&& s
->prev
->face
->underline_p
)
2851 /* We use the same underline style as the previous one. */
2852 thickness
= s
->prev
->underline_thickness
;
2853 position
= s
->prev
->underline_position
;
2857 /* Get the underline thickness. Default is 1 pixel. */
2858 if (s
->font
&& s
->font
->underline_thickness
> 0)
2859 thickness
= s
->font
->underline_thickness
;
2862 if (x_underline_at_descent_line
)
2863 position
= (s
->height
- thickness
) - (s
->ybase
- s
->y
);
2866 /* Get the underline position. This is the recommended
2867 vertical offset in pixels from the baseline to the top of
2868 the underline. This is a signed value according to the
2869 specs, and its default is
2871 ROUND ((maximum descent) / 2), with
2872 ROUND(x) = floor (x + 0.5) */
2874 if (x_use_underline_position_properties
2875 && s
->font
&& s
->font
->underline_position
>= 0)
2876 position
= s
->font
->underline_position
;
2878 position
= (s
->font
->descent
+ 1) / 2;
2880 position
= underline_minimum_offset
;
2882 position
= max (position
, underline_minimum_offset
);
2884 /* Check the sanity of thickness and position. We should
2885 avoid drawing underline out of the current line area. */
2886 if (s
->y
+ s
->height
<= s
->ybase
+ position
)
2887 position
= (s
->height
- 1) - (s
->ybase
- s
->y
);
2888 if (s
->y
+ s
->height
< s
->ybase
+ position
+ thickness
)
2889 thickness
= (s
->y
+ s
->height
) - (s
->ybase
+ position
);
2890 s
->underline_thickness
= thickness
;
2891 s
->underline_position
= position
;
2892 y
= s
->ybase
+ position
;
2893 if (s
->face
->underline_defaulted_p
)
2894 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2895 s
->x
, y
, s
->width
, thickness
);
2899 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2900 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2901 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2902 s
->x
, y
, s
->width
, thickness
);
2903 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2907 /* Draw overline. */
2908 if (s
->face
->overline_p
)
2910 unsigned long dy
= 0, h
= 1;
2912 if (s
->face
->overline_color_defaulted_p
)
2913 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2918 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2919 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2920 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2922 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2926 /* Draw strike-through. */
2927 if (s
->face
->strike_through_p
)
2929 unsigned long h
= 1;
2930 unsigned long dy
= (s
->height
- h
) / 2;
2932 if (s
->face
->strike_through_color_defaulted_p
)
2933 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2938 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2939 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2940 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2942 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2946 /* Draw relief if not yet drawn. */
2947 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2948 x_draw_glyph_string_box (s
);
2952 struct glyph_string
*prev
;
2954 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
2955 if (prev
->hl
!= s
->hl
2956 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
2958 /* As prev was drawn while clipped to its own area, we
2959 must draw the right_overhang part using s->hl now. */
2960 enum draw_glyphs_face save
= prev
->hl
;
2963 x_set_glyph_string_gc (prev
);
2964 x_set_glyph_string_clipping_exactly (s
, prev
);
2965 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
2966 x_draw_glyph_string_foreground (prev
);
2968 x_draw_composite_glyph_string_foreground (prev
);
2969 XSetClipMask (prev
->display
, prev
->gc
, None
);
2971 prev
->num_clips
= 0;
2977 struct glyph_string
*next
;
2979 for (next
= s
->next
; next
; next
= next
->next
)
2980 if (next
->hl
!= s
->hl
2981 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
2983 /* As next will be drawn while clipped to its own area,
2984 we must draw the left_overhang part using s->hl now. */
2985 enum draw_glyphs_face save
= next
->hl
;
2988 x_set_glyph_string_gc (next
);
2989 x_set_glyph_string_clipping_exactly (s
, next
);
2990 if (next
->first_glyph
->type
== CHAR_GLYPH
)
2991 x_draw_glyph_string_foreground (next
);
2993 x_draw_composite_glyph_string_foreground (next
);
2994 XSetClipMask (next
->display
, next
->gc
, None
);
2996 next
->num_clips
= 0;
3001 /* Reset clipping. */
3002 XSetClipMask (s
->display
, s
->gc
, None
);
3006 /* Shift display to make room for inserted glyphs. */
3009 x_shift_glyphs_for_insert (struct frame
*f
, int x
, int y
, int width
, int height
, int shift_by
)
3011 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3012 f
->output_data
.x
->normal_gc
,
3013 x
, y
, width
, height
,
3017 /* Delete N glyphs at the nominal cursor position. Not implemented
3021 x_delete_glyphs (struct frame
*f
, register int n
)
3027 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
3028 If they are <= 0, this is probably an error. */
3031 x_clear_area (Display
*dpy
, Window window
, int x
, int y
, int width
, int height
, int exposures
)
3033 xassert (width
> 0 && height
> 0);
3034 XClearArea (dpy
, window
, x
, y
, width
, height
, exposures
);
3038 /* Clear an entire frame. */
3041 x_clear_frame (struct frame
*f
)
3043 /* Clearing the frame will erase any cursor, so mark them all as no
3045 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3046 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3047 output_cursor
.x
= -1;
3049 /* We don't set the output cursor here because there will always
3050 follow an explicit cursor_to. */
3053 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
3055 /* We have to clear the scroll bars. If we have changed colors or
3056 something like that, then they should be notified. */
3057 x_scroll_bar_clear (f
);
3059 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3060 /* Make sure scroll bars are redrawn. As they aren't redrawn by
3061 redisplay, do it here. */
3062 if (FRAME_GTK_WIDGET (f
))
3063 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
3066 XFlush (FRAME_X_DISPLAY (f
));
3073 /* Invert the middle quarter of the frame for .15 sec. */
3075 /* We use the select system call to do the waiting, so we have to make
3076 sure it's available. If it isn't, we just won't do visual bells. */
3078 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3081 /* Subtract the `struct timeval' values X and Y, storing the result in
3082 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3085 timeval_subtract (struct timeval
*result
, struct timeval x
, struct timeval y
)
3087 /* Perform the carry for the later subtraction by updating y. This
3088 is safer because on some systems the tv_sec member is unsigned. */
3089 if (x
.tv_usec
< y
.tv_usec
)
3091 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3092 y
.tv_usec
-= 1000000 * nsec
;
3096 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3098 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3099 y
.tv_usec
+= 1000000 * nsec
;
3103 /* Compute the time remaining to wait. tv_usec is certainly
3105 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3106 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3108 /* Return indication of whether the result should be considered
3110 return x
.tv_sec
< y
.tv_sec
;
3114 XTflash (struct frame
*f
)
3120 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3121 when the scroll bars and the edit widget share the same X window. */
3122 GdkWindow
*window
= gtk_widget_get_window (FRAME_GTK_WIDGET (f
));
3124 cairo_t
*cr
= gdk_cairo_create (window
);
3125 cairo_set_source_rgb (cr
, 1, 1, 1);
3126 cairo_set_operator (cr
, CAIRO_OPERATOR_DIFFERENCE
);
3127 #define XFillRectangle(d, win, gc, x, y, w, h) \
3129 cairo_rectangle (cr, x, y, w, h); \
3133 #else /* ! HAVE_GTK3 */
3136 vals
.foreground
.pixel
= (FRAME_FOREGROUND_PIXEL (f
)
3137 ^ FRAME_BACKGROUND_PIXEL (f
));
3138 vals
.function
= GDK_XOR
;
3139 gc
= gdk_gc_new_with_values (window
,
3140 &vals
, GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
);
3141 #define XFillRectangle(d, win, gc, x, y, w, h) \
3142 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
3143 #endif /* ! HAVE_GTK3 */
3144 #else /* ! USE_GTK */
3147 /* Create a GC that will use the GXxor function to flip foreground
3148 pixels into background pixels. */
3152 values
.function
= GXxor
;
3153 values
.foreground
= (FRAME_FOREGROUND_PIXEL (f
)
3154 ^ FRAME_BACKGROUND_PIXEL (f
));
3156 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3157 GCFunction
| GCForeground
, &values
);
3161 /* Get the height not including a menu bar widget. */
3162 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3163 /* Height of each line to flash. */
3164 int flash_height
= FRAME_LINE_HEIGHT (f
);
3165 /* These will be the left and right margins of the rectangles. */
3166 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3167 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3171 /* Don't flash the area between a scroll bar and the frame
3172 edge it is next to. */
3173 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3175 case vertical_scroll_bar_left
:
3176 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3179 case vertical_scroll_bar_right
:
3180 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3187 width
= flash_right
- flash_left
;
3189 /* If window is tall, flash top and bottom line. */
3190 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3192 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3194 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3195 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3196 width
, flash_height
);
3197 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3199 (height
- flash_height
3200 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3201 width
, flash_height
);
3205 /* If it is short, flash it all. */
3206 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3207 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3208 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3213 struct timeval wakeup
;
3215 EMACS_GET_TIME (wakeup
);
3217 /* Compute time to wait until, propagating carry from usecs. */
3218 wakeup
.tv_usec
+= 150000;
3219 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3220 wakeup
.tv_usec
%= 1000000;
3222 /* Keep waiting until past the time wakeup or any input gets
3224 while (! detect_input_pending ())
3226 struct timeval current
;
3227 struct timeval timeout
;
3229 EMACS_GET_TIME (current
);
3231 /* Break if result would be negative. */
3232 if (timeval_subtract (¤t
, wakeup
, current
))
3235 /* How long `select' should wait. */
3237 timeout
.tv_usec
= 10000;
3239 /* Try to wait that long--but we might wake up sooner. */
3240 select (0, NULL
, NULL
, NULL
, &timeout
);
3244 /* If window is tall, flash top and bottom line. */
3245 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3247 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3249 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3250 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3251 width
, flash_height
);
3252 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3254 (height
- flash_height
3255 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3256 width
, flash_height
);
3259 /* If it is short, flash it all. */
3260 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3261 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3262 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3268 g_object_unref (G_OBJECT (gc
));
3270 #undef XFillRectangle
3272 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
3281 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3285 XTtoggle_invisible_pointer (FRAME_PTR f
, int invisible
)
3290 if (FRAME_X_DISPLAY_INFO (f
)->invisible_cursor
!= 0)
3291 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3292 FRAME_X_DISPLAY_INFO (f
)->invisible_cursor
);
3295 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3296 f
->output_data
.x
->current_cursor
);
3297 f
->pointer_invisible
= invisible
;
3302 /* Make audible bell. */
3305 XTring_bell (struct frame
*f
)
3307 if (FRAME_X_DISPLAY (f
))
3309 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3316 XBell (FRAME_X_DISPLAY (f
), 0);
3317 XFlush (FRAME_X_DISPLAY (f
));
3324 /* Specify how many text lines, from the top of the window,
3325 should be affected by insert-lines and delete-lines operations.
3326 This, and those operations, are used only within an update
3327 that is bounded by calls to x_update_begin and x_update_end. */
3330 XTset_terminal_window (struct frame
*f
, int n
)
3332 /* This function intentionally left blank. */
3337 /***********************************************************************
3339 ***********************************************************************/
3341 /* Perform an insert-lines or delete-lines operation, inserting N
3342 lines or deleting -N lines at vertical position VPOS. */
3345 x_ins_del_lines (struct frame
*f
, int vpos
, int n
)
3351 /* Scroll part of the display as described by RUN. */
3354 x_scroll_run (struct window
*w
, struct run
*run
)
3356 struct frame
*f
= XFRAME (w
->frame
);
3357 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3359 /* Get frame-relative bounding box of the text display area of W,
3360 without mode lines. Include in this box the left and right
3362 window_box (w
, -1, &x
, &y
, &width
, &height
);
3364 #ifdef USE_TOOLKIT_SCROLL_BARS
3365 /* If the fringe is adjacent to the left (right) scroll bar of a
3366 leftmost (rightmost, respectively) window, then extend its
3367 background to the gap between the fringe and the bar. */
3368 if ((WINDOW_LEFTMOST_P (w
)
3369 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
3370 || (WINDOW_RIGHTMOST_P (w
)
3371 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
3373 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
3377 int bar_area_x
= WINDOW_SCROLL_BAR_AREA_X (w
);
3378 int bar_area_width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
3379 * FRAME_COLUMN_WIDTH (f
));
3381 if (bar_area_x
+ bar_area_width
== x
)
3383 x
= bar_area_x
+ sb_width
;
3384 width
+= bar_area_width
- sb_width
;
3386 else if (x
+ width
== bar_area_x
)
3387 width
+= bar_area_width
- sb_width
;
3392 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3393 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3394 bottom_y
= y
+ height
;
3398 /* Scrolling up. Make sure we don't copy part of the mode
3399 line at the bottom. */
3400 if (from_y
+ run
->height
> bottom_y
)
3401 height
= bottom_y
- from_y
;
3403 height
= run
->height
;
3407 /* Scrolling down. Make sure we don't copy over the mode line.
3409 if (to_y
+ run
->height
> bottom_y
)
3410 height
= bottom_y
- to_y
;
3412 height
= run
->height
;
3417 /* Cursor off. Will be switched on again in x_update_window_end. */
3421 XCopyArea (FRAME_X_DISPLAY (f
),
3422 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3423 f
->output_data
.x
->normal_gc
,
3433 /***********************************************************************
3435 ***********************************************************************/
3439 frame_highlight (struct frame
*f
)
3441 /* We used to only do this if Vx_no_window_manager was non-nil, but
3442 the ICCCM (section 4.1.6) says that the window's border pixmap
3443 and border pixel are window attributes which are "private to the
3444 client", so we can always change it to whatever we want. */
3446 /* I recently started to get errors in this XSetWindowBorder, depending on
3447 the window-manager in use, tho something more is at play since I've been
3448 using that same window-manager binary for ever. Let's not crash just
3449 because of this (bug#9310). */
3450 x_catch_errors (FRAME_X_DISPLAY (f
));
3451 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3452 f
->output_data
.x
->border_pixel
);
3453 x_uncatch_errors ();
3455 x_update_cursor (f
, 1);
3456 x_set_frame_alpha (f
);
3460 frame_unhighlight (struct frame
*f
)
3462 /* We used to only do this if Vx_no_window_manager was non-nil, but
3463 the ICCCM (section 4.1.6) says that the window's border pixmap
3464 and border pixel are window attributes which are "private to the
3465 client", so we can always change it to whatever we want. */
3467 /* Same as above for XSetWindowBorder (bug#9310). */
3468 x_catch_errors (FRAME_X_DISPLAY (f
));
3469 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3470 f
->output_data
.x
->border_tile
);
3471 x_uncatch_errors ();
3473 x_update_cursor (f
, 1);
3474 x_set_frame_alpha (f
);
3477 /* The focus has changed. Update the frames as necessary to reflect
3478 the new situation. Note that we can't change the selected frame
3479 here, because the Lisp code we are interrupting might become confused.
3480 Each event gets marked with the frame in which it occurred, so the
3481 Lisp code can tell when the switch took place by examining the events. */
3484 x_new_focus_frame (struct x_display_info
*dpyinfo
, struct frame
*frame
)
3486 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3488 if (frame
!= dpyinfo
->x_focus_frame
)
3490 /* Set this before calling other routines, so that they see
3491 the correct value of x_focus_frame. */
3492 dpyinfo
->x_focus_frame
= frame
;
3494 if (old_focus
&& old_focus
->auto_lower
)
3495 x_lower_frame (old_focus
);
3497 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3498 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3500 pending_autoraise_frame
= 0;
3503 x_frame_rehighlight (dpyinfo
);
3506 /* Handle FocusIn and FocusOut state changes for FRAME.
3507 If FRAME has focus and there exists more than one frame, puts
3508 a FOCUS_IN_EVENT into *BUFP. */
3511 x_focus_changed (int type
, int state
, struct x_display_info
*dpyinfo
, struct frame
*frame
, struct input_event
*bufp
)
3513 if (type
== FocusIn
)
3515 if (dpyinfo
->x_focus_event_frame
!= frame
)
3517 x_new_focus_frame (dpyinfo
, frame
);
3518 dpyinfo
->x_focus_event_frame
= frame
;
3520 /* Don't stop displaying the initial startup message
3521 for a switch-frame event we don't need. */
3522 if (NILP (Vterminal_frame
)
3523 && CONSP (Vframe_list
)
3524 && !NILP (XCDR (Vframe_list
)))
3526 bufp
->kind
= FOCUS_IN_EVENT
;
3527 XSETFRAME (bufp
->frame_or_window
, frame
);
3531 frame
->output_data
.x
->focus_state
|= state
;
3534 if (FRAME_XIC (frame
))
3535 XSetICFocus (FRAME_XIC (frame
));
3538 else if (type
== FocusOut
)
3540 frame
->output_data
.x
->focus_state
&= ~state
;
3542 if (dpyinfo
->x_focus_event_frame
== frame
)
3544 dpyinfo
->x_focus_event_frame
= 0;
3545 x_new_focus_frame (dpyinfo
, 0);
3549 if (FRAME_XIC (frame
))
3550 XUnsetICFocus (FRAME_XIC (frame
));
3552 if (frame
->pointer_invisible
)
3553 XTtoggle_invisible_pointer (frame
, 0);
3557 /* The focus may have changed. Figure out if it is a real focus change,
3558 by checking both FocusIn/Out and Enter/LeaveNotify events.
3560 Returns FOCUS_IN_EVENT event in *BUFP. */
3563 x_detect_focus_change (struct x_display_info
*dpyinfo
, XEvent
*event
, struct input_event
*bufp
)
3565 struct frame
*frame
;
3567 frame
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
3571 switch (event
->type
)
3576 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3578 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3580 if (event
->xcrossing
.detail
!= NotifyInferior
3581 && event
->xcrossing
.focus
3582 && ! (focus_state
& FOCUS_EXPLICIT
))
3583 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3585 dpyinfo
, frame
, bufp
);
3591 x_focus_changed (event
->type
,
3592 (event
->xfocus
.detail
== NotifyPointer
?
3593 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3594 dpyinfo
, frame
, bufp
);
3598 if (event
->xclient
.message_type
== dpyinfo
->Xatom_XEMBED
)
3600 enum xembed_message msg
= event
->xclient
.data
.l
[1];
3601 x_focus_changed ((msg
== XEMBED_FOCUS_IN
? FocusIn
: FocusOut
),
3602 FOCUS_EXPLICIT
, dpyinfo
, frame
, bufp
);
3609 #if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
3610 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3613 x_mouse_leave (struct x_display_info
*dpyinfo
)
3615 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3619 /* The focus has changed, or we have redirected a frame's focus to
3620 another frame (this happens when a frame uses a surrogate
3621 mini-buffer frame). Shift the highlight as appropriate.
3623 The FRAME argument doesn't necessarily have anything to do with which
3624 frame is being highlighted or un-highlighted; we only use it to find
3625 the appropriate X display info. */
3628 XTframe_rehighlight (struct frame
*frame
)
3630 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3634 x_frame_rehighlight (struct x_display_info
*dpyinfo
)
3636 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3638 if (dpyinfo
->x_focus_frame
)
3640 dpyinfo
->x_highlight_frame
3641 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3642 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3643 : dpyinfo
->x_focus_frame
);
3644 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3646 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3647 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3651 dpyinfo
->x_highlight_frame
= 0;
3653 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3656 frame_unhighlight (old_highlight
);
3657 if (dpyinfo
->x_highlight_frame
)
3658 frame_highlight (dpyinfo
->x_highlight_frame
);
3664 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3666 /* Initialize mode_switch_bit and modifier_meaning. */
3668 x_find_modifier_meanings (struct x_display_info
*dpyinfo
)
3670 int min_code
, max_code
;
3673 XModifierKeymap
*mods
;
3675 dpyinfo
->meta_mod_mask
= 0;
3676 dpyinfo
->shift_lock_mask
= 0;
3677 dpyinfo
->alt_mod_mask
= 0;
3678 dpyinfo
->super_mod_mask
= 0;
3679 dpyinfo
->hyper_mod_mask
= 0;
3681 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3683 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3684 min_code
, max_code
- min_code
+ 1,
3686 mods
= XGetModifierMapping (dpyinfo
->display
);
3688 /* Scan the modifier table to see which modifier bits the Meta and
3689 Alt keysyms are on. */
3691 int row
, col
; /* The row and column in the modifier table. */
3692 int found_alt_or_meta
;
3694 for (row
= 3; row
< 8; row
++)
3696 found_alt_or_meta
= 0;
3697 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3699 KeyCode code
= mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3701 /* Zeroes are used for filler. Skip them. */
3705 /* Are any of this keycode's keysyms a meta key? */
3709 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3711 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3717 found_alt_or_meta
= 1;
3718 dpyinfo
->meta_mod_mask
|= (1 << row
);
3723 found_alt_or_meta
= 1;
3724 dpyinfo
->alt_mod_mask
|= (1 << row
);
3729 if (!found_alt_or_meta
)
3730 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3731 code_col
= syms_per_code
;
3732 col
= mods
->max_keypermod
;
3737 if (!found_alt_or_meta
)
3738 dpyinfo
->super_mod_mask
|= (1 << row
);
3739 code_col
= syms_per_code
;
3740 col
= mods
->max_keypermod
;
3744 /* Ignore this if it's not on the lock modifier. */
3745 if (!found_alt_or_meta
&& ((1 << row
) == LockMask
))
3746 dpyinfo
->shift_lock_mask
= LockMask
;
3747 code_col
= syms_per_code
;
3748 col
= mods
->max_keypermod
;
3757 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3758 if (! dpyinfo
->meta_mod_mask
)
3760 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3761 dpyinfo
->alt_mod_mask
= 0;
3764 /* If some keys are both alt and meta,
3765 make them just meta, not alt. */
3766 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3768 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3771 XFree ((char *) syms
);
3772 XFreeModifiermap (mods
);
3775 /* Convert between the modifier bits X uses and the modifier bits
3779 x_x_to_emacs_modifiers (struct x_display_info
*dpyinfo
, int state
)
3781 int mod_meta
= meta_modifier
;
3782 int mod_alt
= alt_modifier
;
3783 int mod_hyper
= hyper_modifier
;
3784 int mod_super
= super_modifier
;
3787 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3788 if (INTEGERP (tem
)) mod_alt
= XINT (tem
) & INT_MAX
;
3789 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3790 if (INTEGERP (tem
)) mod_meta
= XINT (tem
) & INT_MAX
;
3791 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3792 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
) & INT_MAX
;
3793 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3794 if (INTEGERP (tem
)) mod_super
= XINT (tem
) & INT_MAX
;
3796 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3797 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3798 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3799 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3800 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3801 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3805 x_emacs_to_x_modifiers (struct x_display_info
*dpyinfo
, EMACS_INT state
)
3807 EMACS_INT mod_meta
= meta_modifier
;
3808 EMACS_INT mod_alt
= alt_modifier
;
3809 EMACS_INT mod_hyper
= hyper_modifier
;
3810 EMACS_INT mod_super
= super_modifier
;
3814 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3815 if (INTEGERP (tem
)) mod_alt
= XINT (tem
);
3816 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3817 if (INTEGERP (tem
)) mod_meta
= XINT (tem
);
3818 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3819 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
);
3820 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3821 if (INTEGERP (tem
)) mod_super
= XINT (tem
);
3824 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3825 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3826 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3827 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3828 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3829 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3832 /* Convert a keysym to its name. */
3835 x_get_keysym_name (int keysym
)
3840 value
= XKeysymToString (keysym
);
3848 /* Mouse clicks and mouse movement. Rah. */
3850 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3852 If the event is a button press, then note that we have grabbed
3856 construct_mouse_click (struct input_event
*result
, XButtonEvent
*event
, struct frame
*f
)
3858 /* Make the event type NO_EVENT; we'll change that when we decide
3860 result
->kind
= MOUSE_CLICK_EVENT
;
3861 result
->code
= event
->button
- Button1
;
3862 result
->timestamp
= event
->time
;
3863 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
3865 | (event
->type
== ButtonRelease
3869 XSETINT (result
->x
, event
->x
);
3870 XSETINT (result
->y
, event
->y
);
3871 XSETFRAME (result
->frame_or_window
, f
);
3877 /* Function to report a mouse movement to the mainstream Emacs code.
3878 The input handler calls this.
3880 We have received a mouse movement event, which is given in *event.
3881 If the mouse is over a different glyph than it was last time, tell
3882 the mainstream emacs code by setting mouse_moved. If not, ask for
3883 another motion event, so we can check again the next time it moves. */
3885 static XMotionEvent last_mouse_motion_event
;
3886 static Lisp_Object last_mouse_motion_frame
;
3889 note_mouse_movement (FRAME_PTR frame
, XMotionEvent
*event
)
3891 last_mouse_movement_time
= event
->time
;
3892 last_mouse_motion_event
= *event
;
3893 XSETFRAME (last_mouse_motion_frame
, frame
);
3895 if (!FRAME_X_OUTPUT (frame
))
3898 if (event
->window
!= FRAME_X_WINDOW (frame
))
3900 frame
->mouse_moved
= 1;
3901 last_mouse_scroll_bar
= Qnil
;
3902 note_mouse_highlight (frame
, -1, -1);
3903 last_mouse_glyph_frame
= 0;
3908 /* Has the mouse moved off the glyph it was on at the last sighting? */
3909 if (frame
!= last_mouse_glyph_frame
3910 || event
->x
< last_mouse_glyph
.x
3911 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
3912 || event
->y
< last_mouse_glyph
.y
3913 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
3915 frame
->mouse_moved
= 1;
3916 last_mouse_scroll_bar
= Qnil
;
3917 note_mouse_highlight (frame
, event
->x
, event
->y
);
3918 /* Remember which glyph we're now on. */
3919 remember_mouse_glyph (frame
, event
->x
, event
->y
, &last_mouse_glyph
);
3920 last_mouse_glyph_frame
= frame
;
3928 /************************************************************************
3930 ************************************************************************/
3933 redo_mouse_highlight (void)
3935 if (!NILP (last_mouse_motion_frame
)
3936 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3937 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3938 last_mouse_motion_event
.x
,
3939 last_mouse_motion_event
.y
);
3944 /* Return the current position of the mouse.
3945 *FP should be a frame which indicates which display to ask about.
3947 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3948 and *PART to the frame, window, and scroll bar part that the mouse
3949 is over. Set *X and *Y to the portion and whole of the mouse's
3950 position on the scroll bar.
3952 If the mouse movement started elsewhere, set *FP to the frame the
3953 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3956 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
3957 was at this position.
3959 Don't store anything if we don't have a valid set of values to report.
3961 This clears the mouse_moved flag, so we can wait for the next mouse
3965 XTmouse_position (FRAME_PTR
*fp
, int insist
, Lisp_Object
*bar_window
,
3966 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
3973 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3974 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, timestamp
);
3980 Window dummy_window
;
3983 Lisp_Object frame
, tail
;
3985 /* Clear the mouse-moved flag for every frame on this display. */
3986 FOR_EACH_FRAME (tail
, frame
)
3987 if (FRAME_X_P (XFRAME (frame
))
3988 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3989 XFRAME (frame
)->mouse_moved
= 0;
3991 last_mouse_scroll_bar
= Qnil
;
3993 /* Figure out which root window we're on. */
3994 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3995 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3997 /* The root window which contains the pointer. */
4000 /* Trash which we can't trust if the pointer is on
4001 a different screen. */
4004 /* The position on that root window. */
4007 /* More trash we can't trust. */
4010 /* Modifier keys and pointer buttons, about which
4012 (unsigned int *) &dummy
);
4014 /* Now we have a position on the root; find the innermost window
4015 containing the pointer. */
4019 int parent_x
= 0, parent_y
= 0;
4023 /* XTranslateCoordinates can get errors if the window
4024 structure is changing at the same time this function
4025 is running. So at least we must not crash from them. */
4027 x_catch_errors (FRAME_X_DISPLAY (*fp
));
4029 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4030 && FRAME_LIVE_P (last_mouse_frame
))
4032 /* If mouse was grabbed on a frame, give coords for that frame
4033 even if the mouse is now outside it. */
4034 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4036 /* From-window, to-window. */
4037 root
, FRAME_X_WINDOW (last_mouse_frame
),
4039 /* From-position, to-position. */
4040 root_x
, root_y
, &win_x
, &win_y
,
4044 f1
= last_mouse_frame
;
4050 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4052 /* From-window, to-window. */
4055 /* From-position, to-position. */
4056 root_x
, root_y
, &win_x
, &win_y
,
4061 if (child
== None
|| child
== win
)
4064 /* We don't wan't to know the innermost window. We
4065 want the edit window. For non-Gtk+ the innermost
4066 window is the edit window. For Gtk+ it might not
4067 be. It might be the tool bar for example. */
4068 if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
))
4076 /* Now we know that:
4077 win is the innermost window containing the pointer
4078 (XTC says it has no child containing the pointer),
4079 win_x and win_y are the pointer's position in it
4080 (XTC did this the last time through), and
4081 parent_x and parent_y are the pointer's position in win's parent.
4082 (They are what win_x and win_y were when win was child.
4083 If win is the root window, it has no parent, and
4084 parent_{x,y} are invalid, but that's okay, because we'll
4085 never use them in that case.) */
4088 /* We don't wan't to know the innermost window. We
4089 want the edit window. */
4090 f1
= x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
4092 /* Is win one of our frames? */
4093 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
4096 #ifdef USE_X_TOOLKIT
4097 /* If we end up with the menu bar window, say it's not
4100 && f1
->output_data
.x
->menubar_widget
4101 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
4103 #endif /* USE_X_TOOLKIT */
4106 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
4109 x_uncatch_errors ();
4111 /* If not, is it one of our scroll bars? */
4114 struct scroll_bar
*bar
;
4116 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
4120 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4126 if (f1
== 0 && insist
> 0)
4127 f1
= SELECTED_FRAME ();
4131 /* Ok, we found a frame. Store all the values.
4132 last_mouse_glyph is a rectangle used to reduce the
4133 generation of mouse events. To not miss any motion
4134 events, we must divide the frame into rectangles of the
4135 size of the smallest character that could be displayed
4136 on it, i.e. into the same rectangles that matrices on
4137 the frame are divided into. */
4139 remember_mouse_glyph (f1
, win_x
, win_y
, &last_mouse_glyph
);
4140 last_mouse_glyph_frame
= f1
;
4145 XSETINT (*x
, win_x
);
4146 XSETINT (*y
, win_y
);
4147 *timestamp
= last_mouse_movement_time
;
4157 /***********************************************************************
4159 ***********************************************************************/
4161 /* Scroll bar support. */
4163 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4165 This can be called in GC, so we have to make sure to strip off mark
4168 static struct scroll_bar
*
4169 x_window_to_scroll_bar (Display
*display
, Window window_id
)
4173 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4174 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
4175 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4177 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
4179 Lisp_Object frame
, bar
, condemned
;
4181 frame
= XCAR (tail
);
4182 /* All elements of Vframe_list should be frames. */
4183 if (! FRAMEP (frame
))
4186 if (! FRAME_X_P (XFRAME (frame
)))
4189 /* Scan this frame's scroll bar list for a scroll bar with the
4191 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
4192 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
4193 /* This trick allows us to search both the ordinary and
4194 condemned scroll bar lists with one loop. */
4195 ! NILP (bar
) || (bar
= condemned
,
4198 bar
= XSCROLL_BAR (bar
)->next
)
4199 if (XSCROLL_BAR (bar
)->x_window
== window_id
&&
4200 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
4201 return XSCROLL_BAR (bar
);
4208 #if defined USE_LUCID
4210 /* Return the Lucid menu bar WINDOW is part of. Return null
4211 if WINDOW is not part of a menu bar. */
4214 x_window_to_menu_bar (Window window
)
4218 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
4220 if (FRAME_X_P (XFRAME (XCAR (tail
))))
4222 Lisp_Object frame
= XCAR (tail
);
4223 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
4225 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
4233 #endif /* USE_LUCID */
4236 /************************************************************************
4238 ************************************************************************/
4240 #ifdef USE_TOOLKIT_SCROLL_BARS
4242 static void x_scroll_bar_to_input_event (XEvent
*, struct input_event
*);
4243 static void x_send_scroll_bar_event (Lisp_Object
, int, int, int);
4244 static void x_create_toolkit_scroll_bar (struct frame
*,
4245 struct scroll_bar
*);
4246 static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*,
4250 /* Lisp window being scrolled. Set when starting to interact with
4251 a toolkit scroll bar, reset to nil when ending the interaction. */
4253 static Lisp_Object window_being_scrolled
;
4255 /* Last scroll bar part sent in xm_scroll_callback. */
4257 static int last_scroll_bar_part
;
4259 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4260 that movements of 1/20 of the screen size are mapped to up/down. */
4263 /* Id of action hook installed for scroll bars. */
4265 static XtActionHookId action_hook_id
;
4267 static Boolean xaw3d_arrow_scroll
;
4269 /* Whether the drag scrolling maintains the mouse at the top of the
4270 thumb. If not, resizing the thumb needs to be done more carefully
4271 to avoid jerkiness. */
4273 static Boolean xaw3d_pick_top
;
4275 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4276 bars are used.. The hook is responsible for detecting when
4277 the user ends an interaction with the scroll bar, and generates
4278 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4281 xt_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
4282 XEvent
*event
, String
*params
, Cardinal
*num_params
)
4285 const char *end_action
;
4288 scroll_bar_p
= XmIsScrollBar (widget
);
4289 end_action
= "Release";
4290 #else /* !USE_MOTIF i.e. use Xaw */
4291 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4292 end_action
= "EndScroll";
4293 #endif /* USE_MOTIF */
4296 && strcmp (action_name
, end_action
) == 0
4297 && WINDOWP (window_being_scrolled
))
4301 x_send_scroll_bar_event (window_being_scrolled
,
4302 scroll_bar_end_scroll
, 0, 0);
4303 w
= XWINDOW (window_being_scrolled
);
4305 if (!NILP (XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
))
4307 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
4308 /* The thumb size is incorrect while dragging: fix it. */
4309 set_vertical_scroll_bar (w
);
4311 window_being_scrolled
= Qnil
;
4312 last_scroll_bar_part
= -1;
4314 /* Xt timeouts no longer needed. */
4315 toolkit_scroll_bar_interaction
= 0;
4318 #endif /* not USE_GTK */
4320 /* A vector of windows used for communication between
4321 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4323 static struct window
**scroll_bar_windows
;
4324 static ptrdiff_t scroll_bar_windows_size
;
4327 /* Send a client message with message type Xatom_Scrollbar for a
4328 scroll action to the frame of WINDOW. PART is a value identifying
4329 the part of the scroll bar that was clicked on. PORTION is the
4330 amount to scroll of a whole of WHOLE. */
4333 x_send_scroll_bar_event (Lisp_Object window
, int part
, int portion
, int whole
)
4336 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
4337 struct window
*w
= XWINDOW (window
);
4338 struct frame
*f
= XFRAME (w
->frame
);
4343 /* Construct a ClientMessage event to send to the frame. */
4344 ev
->type
= ClientMessage
;
4345 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4346 ev
->display
= FRAME_X_DISPLAY (f
);
4347 ev
->window
= FRAME_X_WINDOW (f
);
4350 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4351 not enough to store a pointer or Lisp_Object on a 64 bit system.
4352 So, store the window in scroll_bar_windows and pass the index
4353 into that array in the event. */
4354 for (i
= 0; i
< scroll_bar_windows_size
; ++i
)
4355 if (scroll_bar_windows
[i
] == NULL
)
4358 if (i
== scroll_bar_windows_size
)
4360 ptrdiff_t old_nbytes
=
4361 scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4363 enum { XClientMessageEvent_MAX
= 0x7fffffff };
4364 scroll_bar_windows
=
4365 xpalloc (scroll_bar_windows
, &scroll_bar_windows_size
, 1,
4366 XClientMessageEvent_MAX
, sizeof *scroll_bar_windows
);
4367 nbytes
= scroll_bar_windows_size
* sizeof *scroll_bar_windows
;
4368 memset (&scroll_bar_windows
[i
], 0, nbytes
- old_nbytes
);
4371 scroll_bar_windows
[i
] = w
;
4372 ev
->data
.l
[0] = (long) i
;
4373 ev
->data
.l
[1] = (long) part
;
4374 ev
->data
.l
[2] = (long) 0;
4375 ev
->data
.l
[3] = (long) portion
;
4376 ev
->data
.l
[4] = (long) whole
;
4378 /* Make Xt timeouts work while the scroll bar is active. */
4379 #ifdef USE_X_TOOLKIT
4380 toolkit_scroll_bar_interaction
= 1;
4381 x_activate_timeout_atimer ();
4384 /* Setting the event mask to zero means that the message will
4385 be sent to the client that created the window, and if that
4386 window no longer exists, no event will be sent. */
4387 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4392 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4396 x_scroll_bar_to_input_event (XEvent
*event
, struct input_event
*ievent
)
4398 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
4402 w
= scroll_bar_windows
[ev
->data
.l
[0]];
4403 scroll_bar_windows
[ev
->data
.l
[0]] = NULL
;
4405 XSETWINDOW (window
, w
);
4407 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4408 ievent
->frame_or_window
= window
;
4411 ievent
->timestamp
= CurrentTime
;
4414 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
4416 ievent
->part
= ev
->data
.l
[1];
4417 ievent
->code
= ev
->data
.l
[2];
4418 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
4419 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
4420 ievent
->modifiers
= 0;
4426 /* Minimum and maximum values used for Motif scroll bars. */
4428 #define XM_SB_MAX 10000000
4431 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4432 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4433 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4436 xm_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4438 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4439 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
4440 int part
= -1, whole
= 0, portion
= 0;
4444 case XmCR_DECREMENT
:
4445 bar
->dragging
= Qnil
;
4446 part
= scroll_bar_up_arrow
;
4449 case XmCR_INCREMENT
:
4450 bar
->dragging
= Qnil
;
4451 part
= scroll_bar_down_arrow
;
4454 case XmCR_PAGE_DECREMENT
:
4455 bar
->dragging
= Qnil
;
4456 part
= scroll_bar_above_handle
;
4459 case XmCR_PAGE_INCREMENT
:
4460 bar
->dragging
= Qnil
;
4461 part
= scroll_bar_below_handle
;
4465 bar
->dragging
= Qnil
;
4466 part
= scroll_bar_to_top
;
4469 case XmCR_TO_BOTTOM
:
4470 bar
->dragging
= Qnil
;
4471 part
= scroll_bar_to_bottom
;
4478 /* Get the slider size. */
4480 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4483 whole
= XM_SB_MAX
- slider_size
;
4484 portion
= min (cs
->value
, whole
);
4485 part
= scroll_bar_handle
;
4486 bar
->dragging
= make_number (cs
->value
);
4490 case XmCR_VALUE_CHANGED
:
4496 window_being_scrolled
= bar
->window
;
4497 last_scroll_bar_part
= part
;
4498 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4502 #elif defined USE_GTK
4504 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4505 bar widget. DATA is a pointer to the scroll_bar structure. */
4508 xg_scroll_callback (GtkRange
*range
,
4509 GtkScrollType scroll
,
4513 struct scroll_bar
*bar
= (struct scroll_bar
*) user_data
;
4515 int part
= -1, whole
= 0, portion
= 0;
4516 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (range
));
4517 FRAME_PTR f
= (FRAME_PTR
) g_object_get_data (G_OBJECT (range
), XG_FRAME_DATA
);
4519 if (xg_ignore_gtk_scrollbar
) return FALSE
;
4520 position
= gtk_adjustment_get_value (adj
);
4525 case GTK_SCROLL_JUMP
:
4526 /* Buttons 1 2 or 3 must be grabbed. */
4527 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
!= 0
4528 && FRAME_X_DISPLAY_INFO (f
)->grabbed
< (1 << 4))
4530 part
= scroll_bar_handle
;
4531 whole
= gtk_adjustment_get_upper (adj
) -
4532 gtk_adjustment_get_page_size (adj
);
4533 portion
= min ((int)position
, whole
);
4534 bar
->dragging
= make_number ((int)portion
);
4537 case GTK_SCROLL_STEP_BACKWARD
:
4538 part
= scroll_bar_up_arrow
;
4539 bar
->dragging
= Qnil
;
4541 case GTK_SCROLL_STEP_FORWARD
:
4542 part
= scroll_bar_down_arrow
;
4543 bar
->dragging
= Qnil
;
4545 case GTK_SCROLL_PAGE_BACKWARD
:
4546 part
= scroll_bar_above_handle
;
4547 bar
->dragging
= Qnil
;
4549 case GTK_SCROLL_PAGE_FORWARD
:
4550 part
= scroll_bar_below_handle
;
4551 bar
->dragging
= Qnil
;
4557 window_being_scrolled
= bar
->window
;
4558 last_scroll_bar_part
= part
;
4559 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4565 /* Callback for button release. Sets dragging to Qnil when dragging is done. */
4568 xg_end_scroll_callback (GtkWidget
*widget
,
4569 GdkEventButton
*event
,
4572 struct scroll_bar
*bar
= (struct scroll_bar
*) user_data
;
4573 bar
->dragging
= Qnil
;
4574 if (WINDOWP (window_being_scrolled
))
4576 x_send_scroll_bar_event (window_being_scrolled
,
4577 scroll_bar_end_scroll
, 0, 0);
4578 window_being_scrolled
= Qnil
;
4585 #else /* not USE_GTK and not USE_MOTIF */
4587 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4588 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4589 scroll bar struct. CALL_DATA is a pointer to a float saying where
4593 xaw_jump_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4595 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4596 float top
= *(float *) call_data
;
4598 int whole
, portion
, height
;
4601 /* Get the size of the thumb, a value between 0 and 1. */
4603 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4607 portion
= shown
< 1 ? top
* whole
: 0;
4609 if (shown
< 1 && (eabs (top
+ shown
- 1) < 1.0f
/ height
))
4610 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4611 the bottom, so we force the scrolling whenever we see that we're
4612 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4613 we try to ensure that we always stay two pixels away from the
4615 part
= scroll_bar_down_arrow
;
4617 part
= scroll_bar_handle
;
4619 window_being_scrolled
= bar
->window
;
4620 bar
->dragging
= make_number (portion
);
4621 last_scroll_bar_part
= part
;
4622 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4626 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4627 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4628 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4629 the scroll bar. CALL_DATA is an integer specifying the action that
4630 has taken place. Its magnitude is in the range 0..height of the
4631 scroll bar. Negative values mean scroll towards buffer start.
4632 Values < height of scroll bar mean line-wise movement. */
4635 xaw_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4637 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
4638 /* The position really is stored cast to a pointer. */
4639 int position
= (long) call_data
;
4643 /* Get the height of the scroll bar. */
4645 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4648 if (eabs (position
) >= height
)
4649 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4651 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4652 it maps line-movement to call_data = max(5, height/20). */
4653 else if (xaw3d_arrow_scroll
&& eabs (position
) <= max (5, height
/ 20))
4654 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4656 part
= scroll_bar_move_ratio
;
4658 window_being_scrolled
= bar
->window
;
4659 bar
->dragging
= Qnil
;
4660 last_scroll_bar_part
= part
;
4661 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4664 #endif /* not USE_GTK and not USE_MOTIF */
4666 #define SCROLL_BAR_NAME "verticalScrollBar"
4668 /* Create the widget for scroll bar BAR on frame F. Record the widget
4669 and X window of the scroll bar in BAR. */
4673 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
4675 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
4678 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4679 G_CALLBACK (xg_end_scroll_callback
),
4684 #else /* not USE_GTK */
4687 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
4693 char const *scroll_bar_name
= SCROLL_BAR_NAME
;
4694 unsigned long pixel
;
4699 /* Set resources. Create the widget. */
4700 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4701 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4702 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4703 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4704 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4705 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4706 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4708 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4711 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4715 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4718 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4722 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4723 scroll_bar_name
, av
, ac
);
4725 /* Add one callback for everything that can happen. */
4726 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4728 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4730 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4732 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4734 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4736 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4738 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4741 /* Realize the widget. Only after that is the X window created. */
4742 XtRealizeWidget (widget
);
4744 /* Set the cursor to an arrow. I didn't find a resource to do that.
4745 And I'm wondering why it hasn't an arrow cursor by default. */
4746 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4747 f
->output_data
.x
->nontext_cursor
);
4749 #else /* !USE_MOTIF i.e. use Xaw */
4751 /* Set resources. Create the widget. The background of the
4752 Xaw3d scroll bar widget is a little bit light for my taste.
4753 We don't alter it here to let users change it according
4754 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4755 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4756 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4757 /* For smoother scrolling with Xaw3d -sm */
4758 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4760 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4763 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4767 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4770 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4774 /* Top/bottom shadow colors. */
4776 /* Allocate them, if necessary. */
4777 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4779 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4782 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
4783 FRAME_X_COLORMAP (f
),
4784 &pixel
, 1.2, 0x8000))
4786 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4789 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4791 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4794 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
4795 FRAME_X_COLORMAP (f
),
4796 &pixel
, 0.6, 0x4000))
4798 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4802 #ifdef XtNbeNiceToColormap
4803 /* Tell the toolkit about them. */
4804 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4805 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4806 /* We tried to allocate a color for the top/bottom shadow, and
4807 failed, so tell Xaw3d to use dithering instead. */
4808 /* But only if we have a small colormap. Xaw3d can allocate nice
4811 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
4812 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
4816 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4817 be more consistent with other emacs 3d colors, and since Xaw3d is
4818 not good at dealing with allocation failure. */
4820 /* This tells Xaw3d to use real colors instead of dithering for
4822 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4825 /* Specify the colors. */
4826 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4829 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
4832 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4835 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
4841 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4842 f
->output_data
.x
->edit_widget
, av
, ac
);
4845 char const *initial
= "";
4846 char const *val
= initial
;
4847 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4848 #ifdef XtNarrowScrollbars
4849 XtNarrowScrollbars
, (XtPointer
) &xaw3d_arrow_scroll
,
4851 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4852 if (xaw3d_arrow_scroll
|| val
== initial
)
4853 { /* ARROW_SCROLL */
4854 xaw3d_arrow_scroll
= True
;
4855 /* Isn't that just a personal preference ? --Stef */
4856 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4860 /* Define callbacks. */
4861 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4862 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4865 /* Realize the widget. Only after that is the X window created. */
4866 XtRealizeWidget (widget
);
4868 #endif /* !USE_MOTIF */
4870 /* Install an action hook that lets us detect when the user
4871 finishes interacting with a scroll bar. */
4872 if (action_hook_id
== 0)
4873 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4875 /* Remember X window and widget in the scroll bar vector. */
4876 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4877 xwindow
= XtWindow (widget
);
4878 bar
->x_window
= xwindow
;
4882 #endif /* not USE_GTK */
4885 /* Set the thumb size and position of scroll bar BAR. We are currently
4886 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4890 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
, int whole
)
4892 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4895 #else /* not USE_GTK */
4897 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
4900 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4901 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4908 /* We use an estimate of 30 chars per line rather than the real
4909 `portion' value. This has the disadvantage that the thumb size
4910 is not very representative, but it makes our life a lot easier.
4911 Otherwise, we have to constantly adjust the thumb size, which
4912 we can't always do quickly enough: while dragging, the size of
4913 the thumb might prevent the user from dragging the thumb all the
4914 way to the end. but Motif and some versions of Xaw3d don't allow
4915 updating the thumb size while dragging. Also, even if we can update
4916 its size, the update will often happen too late.
4917 If you don't believe it, check out revision 1.650 of xterm.c to see
4918 what hoops we were going through and the still poor behavior we got. */
4919 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4920 /* When the thumb is at the bottom, position == whole.
4921 So we need to increase `whole' to make space for the thumb. */
4928 top
= (float) position
/ whole
;
4929 shown
= (float) portion
/ whole
;
4932 if (NILP (bar
->dragging
))
4936 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4937 is the scroll bar's maximum and MIN is the scroll bar's minimum
4939 size
= shown
* XM_SB_MAX
;
4940 size
= min (size
, XM_SB_MAX
);
4941 size
= max (size
, 1);
4943 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4944 value
= top
* XM_SB_MAX
;
4945 value
= min (value
, XM_SB_MAX
- size
);
4947 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4949 #else /* !USE_MOTIF i.e. use Xaw */
4955 top
= (float) position
/ whole
;
4956 shown
= (float) portion
/ whole
;
4960 float old_top
, old_shown
;
4962 XtVaGetValues (widget
,
4963 XtNtopOfThumb
, &old_top
,
4964 XtNshown
, &old_shown
,
4968 /* Massage the top+shown values. */
4969 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
4970 top
= max (0, min (1, top
));
4973 /* Keep two pixels available for moving the thumb down. */
4974 shown
= max (0, min (1 - top
- (2.0f
/ height
), shown
));
4976 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4977 check that your system's configuration file contains a define
4978 for `NARROWPROTO'. See s/freebsd.h for an example. */
4979 if (top
!= old_top
|| shown
!= old_shown
)
4981 if (NILP (bar
->dragging
))
4982 XawScrollbarSetThumb (widget
, top
, shown
);
4985 /* Try to make the scrolling a tad smoother. */
4986 if (!xaw3d_pick_top
)
4987 shown
= min (shown
, old_shown
);
4989 XawScrollbarSetThumb (widget
, top
, shown
);
4993 #endif /* !USE_MOTIF */
4997 #endif /* not USE_GTK */
4999 #endif /* USE_TOOLKIT_SCROLL_BARS */
5003 /************************************************************************
5004 Scroll bars, general
5005 ************************************************************************/
5007 /* Create a scroll bar and return the scroll bar vector for it. W is
5008 the Emacs window on which to create the scroll bar. TOP, LEFT,
5009 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5012 static struct scroll_bar
*
5013 x_scroll_bar_create (struct window
*w
, int top
, int left
, int width
, int height
)
5015 struct frame
*f
= XFRAME (w
->frame
);
5016 struct scroll_bar
*bar
5017 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar
, x_window
, PVEC_OTHER
);
5021 #ifdef USE_TOOLKIT_SCROLL_BARS
5022 x_create_toolkit_scroll_bar (f
, bar
);
5023 #else /* not USE_TOOLKIT_SCROLL_BARS */
5025 XSetWindowAttributes a
;
5029 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
5030 if (a
.background_pixel
== -1)
5031 a
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
5033 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
5034 | ButtonMotionMask
| PointerMotionHintMask
5036 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
5038 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
5040 /* Clear the area of W that will serve as a scroll bar. This is
5041 for the case that a window has been split horizontally. In
5042 this case, no clear_frame is generated to reduce flickering. */
5043 if (width
> 0 && height
> 0)
5044 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5046 window_box_height (w
), False
);
5048 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5049 /* Position and size of scroll bar. */
5050 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5052 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5054 /* Border width, depth, class, and visual. */
5061 bar
->x_window
= window
;
5063 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5065 XSETWINDOW (bar
->window
, w
);
5069 bar
->height
= height
;
5072 bar
->dragging
= Qnil
;
5073 bar
->fringe_extended_p
= 0;
5075 /* Add bar to its frame's list of scroll bars. */
5076 bar
->next
= FRAME_SCROLL_BARS (f
);
5078 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5079 if (!NILP (bar
->next
))
5080 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5082 /* Map the window/widget. */
5083 #ifdef USE_TOOLKIT_SCROLL_BARS
5086 xg_update_scrollbar_pos (f
,
5089 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5090 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5092 #else /* not USE_GTK */
5093 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
5094 XtConfigureWidget (scroll_bar
,
5095 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5097 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5098 max (height
, 1), 0);
5099 XtMapWidget (scroll_bar
);
5100 #endif /* not USE_GTK */
5102 #else /* not USE_TOOLKIT_SCROLL_BARS */
5103 XMapRaised (FRAME_X_DISPLAY (f
), bar
->x_window
);
5104 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5111 #ifndef USE_TOOLKIT_SCROLL_BARS
5113 /* Draw BAR's handle in the proper position.
5115 If the handle is already drawn from START to END, don't bother
5116 redrawing it, unless REBUILD is non-zero; in that case, always
5117 redraw it. (REBUILD is handy for drawing the handle after expose
5120 Normally, we want to constrain the start and end of the handle to
5121 fit inside its rectangle, but if the user is dragging the scroll
5122 bar handle, we want to let them drag it down all the way, so that
5123 the bar's top is as far down as it goes; otherwise, there's no way
5124 to move to the very end of the buffer. */
5127 x_scroll_bar_set_handle (struct scroll_bar
*bar
, int start
, int end
, int rebuild
)
5129 int dragging
= ! NILP (bar
->dragging
);
5130 Window w
= bar
->x_window
;
5131 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5132 GC gc
= f
->output_data
.x
->normal_gc
;
5134 /* If the display is already accurate, do nothing. */
5136 && start
== bar
->start
5143 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, bar
->width
);
5144 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, bar
->height
);
5145 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5147 /* Make sure the values are reasonable, and try to preserve
5148 the distance between start and end. */
5150 int length
= end
- start
;
5154 else if (start
> top_range
)
5156 end
= start
+ length
;
5160 else if (end
> top_range
&& ! dragging
)
5164 /* Store the adjusted setting in the scroll bar. */
5168 /* Clip the end position, just for display. */
5169 if (end
> top_range
)
5172 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
5173 below top positions, to make sure the handle is always at least
5174 that many pixels tall. */
5175 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5177 /* Draw the empty space above the handle. Note that we can't clear
5178 zero-height areas; that means "clear to end of window." */
5180 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5181 /* x, y, width, height, and exposures. */
5182 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5183 VERTICAL_SCROLL_BAR_TOP_BORDER
,
5184 inside_width
, start
,
5187 /* Change to proper foreground color if one is specified. */
5188 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5189 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5190 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5192 /* Draw the handle itself. */
5193 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5194 /* x, y, width, height */
5195 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5196 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
5197 inside_width
, end
- start
);
5199 /* Restore the foreground color of the GC if we changed it above. */
5200 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5201 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5202 FRAME_FOREGROUND_PIXEL (f
));
5204 /* Draw the empty space below the handle. Note that we can't
5205 clear zero-height areas; that means "clear to end of window." */
5206 if (end
< inside_height
)
5207 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5208 /* x, y, width, height, and exposures. */
5209 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5210 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
5211 inside_width
, inside_height
- end
,
5219 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5221 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5225 x_scroll_bar_remove (struct scroll_bar
*bar
)
5227 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5230 #ifdef USE_TOOLKIT_SCROLL_BARS
5232 xg_remove_scroll_bar (f
, bar
->x_window
);
5233 #else /* not USE_GTK */
5234 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
5235 #endif /* not USE_GTK */
5237 XDestroyWindow (FRAME_X_DISPLAY (f
), bar
->x_window
);
5240 /* Dissociate this scroll bar from its window. */
5241 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5247 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5248 that we are displaying PORTION characters out of a total of WHOLE
5249 characters, starting at POSITION. If WINDOW has no scroll bar,
5253 XTset_vertical_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
5255 struct frame
*f
= XFRAME (w
->frame
);
5256 struct scroll_bar
*bar
;
5257 int top
, height
, left
, sb_left
, width
, sb_width
;
5258 int window_y
, window_height
;
5259 #ifdef USE_TOOLKIT_SCROLL_BARS
5260 int fringe_extended_p
;
5263 /* Get window dimensions. */
5264 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
5266 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5267 height
= window_height
;
5269 /* Compute the left edge of the scroll bar area. */
5270 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5272 /* Compute the width of the scroll bar which might be less than
5273 the width of the area reserved for the scroll bar. */
5274 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
5275 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
5279 /* Compute the left edge of the scroll bar. */
5280 #ifdef USE_TOOLKIT_SCROLL_BARS
5281 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5282 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
5284 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
5286 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
5287 sb_left
= left
+ width
- sb_width
;
5292 #ifdef USE_TOOLKIT_SCROLL_BARS
5293 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5294 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
5295 && WINDOW_LEFT_FRINGE_WIDTH (w
)
5296 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5297 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
5299 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
5300 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
5301 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
5302 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
5305 /* Does the scroll bar exist yet? */
5306 if (NILP (w
->vertical_scroll_bar
))
5308 if (width
> 0 && height
> 0)
5311 #ifdef USE_TOOLKIT_SCROLL_BARS
5312 if (fringe_extended_p
)
5313 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5314 sb_left
, top
, sb_width
, height
, False
);
5317 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5318 left
, top
, width
, height
, False
);
5322 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5326 /* It may just need to be moved and resized. */
5327 unsigned int mask
= 0;
5329 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5333 if (sb_left
!= bar
->left
)
5335 if (top
!= bar
->top
)
5337 if (sb_width
!= bar
->width
)
5339 if (height
!= bar
->height
)
5342 #ifdef USE_TOOLKIT_SCROLL_BARS
5344 /* Move/size the scroll bar widget. */
5345 if (mask
|| bar
->fringe_extended_p
!= fringe_extended_p
)
5347 /* Since toolkit scroll bars are smaller than the space reserved
5348 for them on the frame, we have to clear "under" them. */
5349 if (width
> 0 && height
> 0)
5351 if (fringe_extended_p
)
5352 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5353 sb_left
, top
, sb_width
, height
, False
);
5355 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5356 left
, top
, width
, height
, False
);
5359 xg_update_scrollbar_pos (f
,
5362 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5363 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
*2,
5365 #else /* not USE_GTK */
5366 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5367 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5369 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5370 max (height
, 1), 0);
5371 #endif /* not USE_GTK */
5373 #else /* not USE_TOOLKIT_SCROLL_BARS */
5375 /* Clear areas not covered by the scroll bar because of
5376 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5377 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
5379 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5380 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5382 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5383 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5384 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5388 /* Clear areas not covered by the scroll bar because it's not as
5389 wide as the area reserved for it. This makes sure a
5390 previous mode line display is cleared after C-x 2 C-x 1, for
5393 int area_width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
5394 int rest
= area_width
- sb_width
;
5395 if (rest
> 0 && height
> 0)
5397 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
5398 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5399 left
+ area_width
- rest
, top
,
5400 rest
, height
, False
);
5402 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5403 left
, top
, rest
, height
, False
);
5407 /* Move/size the scroll bar window. */
5412 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5414 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
5416 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
5420 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5422 /* Remember new settings. */
5423 bar
->left
= sb_left
;
5425 bar
->width
= sb_width
;
5426 bar
->height
= height
;
5431 #ifdef USE_TOOLKIT_SCROLL_BARS
5432 bar
->fringe_extended_p
= fringe_extended_p
;
5434 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5435 #else /* not USE_TOOLKIT_SCROLL_BARS */
5436 /* Set the scroll bar's current state, unless we're currently being
5438 if (NILP (bar
->dragging
))
5440 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5443 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5446 int start
= ((double) position
* top_range
) / whole
;
5447 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5448 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5451 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5453 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5457 /* The following three hooks are used when we're doing a thorough
5458 redisplay of the frame. We don't explicitly know which scroll bars
5459 are going to be deleted, because keeping track of when windows go
5460 away is a real pain - "Can you say set-window-configuration, boys
5461 and girls?" Instead, we just assert at the beginning of redisplay
5462 that *all* scroll bars are to be removed, and then save a scroll bar
5463 from the fiery pit when we actually redisplay its window. */
5465 /* Arrange for all scroll bars on FRAME to be removed at the next call
5466 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5467 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5470 XTcondemn_scroll_bars (FRAME_PTR frame
)
5472 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5473 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5476 bar
= FRAME_SCROLL_BARS (frame
);
5477 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5478 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5479 XSCROLL_BAR (bar
)->prev
= Qnil
;
5480 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5481 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5482 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5487 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5488 Note that WINDOW isn't necessarily condemned at all. */
5491 XTredeem_scroll_bar (struct window
*window
)
5493 struct scroll_bar
*bar
;
5496 /* We can't redeem this window's scroll bar if it doesn't have one. */
5497 if (NILP (window
->vertical_scroll_bar
))
5500 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5502 /* Unlink it from the condemned list. */
5503 f
= XFRAME (WINDOW_FRAME (window
));
5504 if (NILP (bar
->prev
))
5506 /* If the prev pointer is nil, it must be the first in one of
5508 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5509 /* It's not condemned. Everything's fine. */
5511 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5512 window
->vertical_scroll_bar
))
5513 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5515 /* If its prev pointer is nil, it must be at the front of
5516 one or the other! */
5520 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5522 if (! NILP (bar
->next
))
5523 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5525 bar
->next
= FRAME_SCROLL_BARS (f
);
5527 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5528 if (! NILP (bar
->next
))
5529 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5532 /* Remove all scroll bars on FRAME that haven't been saved since the
5533 last call to `*condemn_scroll_bars_hook'. */
5536 XTjudge_scroll_bars (FRAME_PTR f
)
5538 Lisp_Object bar
, next
;
5540 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5542 /* Clear out the condemned list now so we won't try to process any
5543 more events on the hapless scroll bars. */
5544 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5546 for (; ! NILP (bar
); bar
= next
)
5548 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5550 x_scroll_bar_remove (b
);
5553 b
->next
= b
->prev
= Qnil
;
5556 /* Now there should be no references to the condemned scroll bars,
5557 and they should get garbage-collected. */
5561 #ifndef USE_TOOLKIT_SCROLL_BARS
5562 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5563 is a no-op when using toolkit scroll bars.
5565 This may be called from a signal handler, so we have to ignore GC
5569 x_scroll_bar_expose (struct scroll_bar
*bar
, XEvent
*event
)
5571 Window w
= bar
->x_window
;
5572 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5573 GC gc
= f
->output_data
.x
->normal_gc
;
5574 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5578 x_scroll_bar_set_handle (bar
, bar
->start
, bar
->end
, 1);
5580 /* Switch to scroll bar foreground color. */
5581 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5582 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5583 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5585 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5586 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5588 /* x, y, width, height */
5590 bar
->width
- 1 - width_trim
- width_trim
,
5593 /* Restore the foreground color of the GC if we changed it above. */
5594 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5595 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5596 FRAME_FOREGROUND_PIXEL (f
));
5601 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5603 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5604 is set to something other than NO_EVENT, it is enqueued.
5606 This may be called from a signal handler, so we have to ignore GC
5611 x_scroll_bar_handle_click (struct scroll_bar
*bar
, XEvent
*event
, struct input_event
*emacs_event
)
5613 if (! WINDOWP (bar
->window
))
5616 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5617 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5618 emacs_event
->modifiers
5619 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5620 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5621 event
->xbutton
.state
)
5622 | (event
->type
== ButtonRelease
5625 emacs_event
->frame_or_window
= bar
->window
;
5626 emacs_event
->arg
= Qnil
;
5627 emacs_event
->timestamp
= event
->xbutton
.time
;
5630 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5631 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5634 if (y
> top_range
) y
= top_range
;
5637 emacs_event
->part
= scroll_bar_above_handle
;
5638 else if (y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5639 emacs_event
->part
= scroll_bar_handle
;
5641 emacs_event
->part
= scroll_bar_below_handle
;
5643 #ifndef USE_TOOLKIT_SCROLL_BARS
5644 /* If the user has released the handle, set it to its final position. */
5645 if (event
->type
== ButtonRelease
5646 && ! NILP (bar
->dragging
))
5648 int new_start
= y
- XINT (bar
->dragging
);
5649 int new_end
= new_start
+ bar
->end
- bar
->start
;
5651 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5652 bar
->dragging
= Qnil
;
5656 XSETINT (emacs_event
->x
, y
);
5657 XSETINT (emacs_event
->y
, top_range
);
5661 #ifndef USE_TOOLKIT_SCROLL_BARS
5663 /* Handle some mouse motion while someone is dragging the scroll bar.
5665 This may be called from a signal handler, so we have to ignore GC
5669 x_scroll_bar_note_movement (struct scroll_bar
*bar
, XEvent
*event
)
5671 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5673 last_mouse_movement_time
= event
->xmotion
.time
;
5676 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5678 /* If we're dragging the bar, display it. */
5679 if (! NILP (bar
->dragging
))
5681 /* Where should the handle be now? */
5682 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
5684 if (new_start
!= bar
->start
)
5686 int new_end
= new_start
+ bar
->end
- bar
->start
;
5688 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5693 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5695 /* Return information to the user about the current position of the mouse
5696 on the scroll bar. */
5699 x_scroll_bar_report_motion (FRAME_PTR
*fp
, Lisp_Object
*bar_window
,
5700 enum scroll_bar_part
*part
, Lisp_Object
*x
,
5701 Lisp_Object
*y
, Time
*timestamp
)
5703 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5704 Window w
= bar
->x_window
;
5705 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5707 Window dummy_window
;
5709 unsigned int dummy_mask
;
5713 /* Get the mouse's position relative to the scroll bar window, and
5715 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5717 /* Root, child, root x and root y. */
5718 &dummy_window
, &dummy_window
,
5719 &dummy_coord
, &dummy_coord
,
5721 /* Position relative to scroll bar. */
5724 /* Mouse buttons and modifier keys. */
5730 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5732 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5734 if (! NILP (bar
->dragging
))
5735 win_y
-= XINT (bar
->dragging
);
5739 if (win_y
> top_range
)
5743 *bar_window
= bar
->window
;
5745 if (! NILP (bar
->dragging
))
5746 *part
= scroll_bar_handle
;
5747 else if (win_y
< bar
->start
)
5748 *part
= scroll_bar_above_handle
;
5749 else if (win_y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5750 *part
= scroll_bar_handle
;
5752 *part
= scroll_bar_below_handle
;
5754 XSETINT (*x
, win_y
);
5755 XSETINT (*y
, top_range
);
5758 last_mouse_scroll_bar
= Qnil
;
5761 *timestamp
= last_mouse_movement_time
;
5767 /* The screen has been cleared so we may have changed foreground or
5768 background colors, and the scroll bars may need to be redrawn.
5769 Clear out the scroll bars, and ask for expose events, so we can
5773 x_scroll_bar_clear (FRAME_PTR f
)
5775 #ifndef USE_TOOLKIT_SCROLL_BARS
5778 /* We can have scroll bars even if this is 0,
5779 if we just turned off scroll bar mode.
5780 But in that case we should not clear them. */
5781 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5782 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5783 bar
= XSCROLL_BAR (bar
)->next
)
5784 XClearArea (FRAME_X_DISPLAY (f
),
5785 XSCROLL_BAR (bar
)->x_window
,
5787 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5791 /* The main X event-reading loop - XTread_socket. */
5793 /* This holds the state XLookupString needs to implement dead keys
5794 and other tricks known as "compose processing". _X Window System_
5795 says that a portable program can't use this, but Stephen Gildea assures
5796 me that letting the compiler initialize it to zeros will work okay.
5798 This must be defined outside of XTread_socket, for the same reasons
5799 given for enter_timestamp, above. */
5801 static XComposeStatus compose_status
;
5803 /* Record the last 100 characters stored
5804 to help debug the loss-of-chars-during-GC problem. */
5806 static int temp_index
;
5807 static short temp_buffer
[100];
5809 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5810 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5812 temp_buffer[temp_index++] = (keysym)
5814 /* Set this to nonzero to fake an "X I/O error"
5815 on a particular display. */
5817 static struct x_display_info
*XTread_socket_fake_io_error
;
5819 /* When we find no input here, we occasionally do a no-op command
5820 to verify that the X server is still running and we can still talk with it.
5821 We try all the open displays, one by one.
5822 This variable is used for cycling thru the displays. */
5824 static struct x_display_info
*next_noop_dpyinfo
;
5826 #if defined USE_X_TOOLKIT || defined USE_GTK
5827 #define SET_SAVED_BUTTON_EVENT \
5830 if (f->output_data.x->saved_menu_event == 0) \
5831 f->output_data.x->saved_menu_event \
5832 = (XEvent *) xmalloc (sizeof (XEvent)); \
5833 *f->output_data.x->saved_menu_event = event; \
5834 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5835 XSETFRAME (inev.ie.frame_or_window, f); \
5847 /* Filter events for the current X input method.
5848 DPYINFO is the display this event is for.
5849 EVENT is the X event to filter.
5851 Returns non-zero if the event was filtered, caller shall not process
5853 Returns zero if event is wasn't filtered. */
5857 x_filter_event (struct x_display_info
*dpyinfo
, XEvent
*event
)
5859 /* XFilterEvent returns non-zero if the input method has
5860 consumed the event. We pass the frame's X window to
5861 XFilterEvent because that's the one for which the IC
5864 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5865 event
->xclient
.window
);
5867 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5872 static int current_count
;
5873 static int current_finish
;
5874 static struct input_event
*current_hold_quit
;
5876 /* This is the filter function invoked by the GTK event loop.
5877 It is invoked before the XEvent is translated to a GdkEvent,
5878 so we have a chance to act on the event before GTK. */
5879 static GdkFilterReturn
5880 event_handler_gdk (GdkXEvent
*gxev
, GdkEvent
*ev
, gpointer data
)
5882 XEvent
*xev
= (XEvent
*) gxev
;
5885 if (current_count
>= 0)
5887 struct x_display_info
*dpyinfo
;
5889 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5892 /* Filter events for the current X input method.
5893 GTK calls XFilterEvent but not for key press and release,
5894 so we do it here. */
5895 if ((xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5897 && x_filter_event (dpyinfo
, xev
))
5900 return GDK_FILTER_REMOVE
;
5905 current_finish
= X_EVENT_NORMAL
;
5908 handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5912 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5916 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5917 return GDK_FILTER_REMOVE
;
5919 return GDK_FILTER_CONTINUE
;
5921 #endif /* USE_GTK */
5924 static void xembed_send_message (struct frame
*f
, Time
,
5925 enum xembed_message
,
5926 long detail
, long data1
, long data2
);
5928 /* Handles the XEvent EVENT on display DPYINFO.
5930 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5931 *FINISH is zero if caller should continue reading events.
5932 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5934 We return the number of characters stored into the buffer. */
5937 handle_one_xevent (struct x_display_info
*dpyinfo
, XEvent
*eventptr
,
5938 int *finish
, struct input_event
*hold_quit
)
5941 struct input_event ie
;
5942 struct selection_input_event sie
;
5946 ptrdiff_t nbytes
= 0;
5947 struct frame
*f
= NULL
;
5948 struct coding_system coding
;
5949 XEvent event
= *eventptr
;
5950 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
5953 *finish
= X_EVENT_NORMAL
;
5955 EVENT_INIT (inev
.ie
);
5956 inev
.ie
.kind
= NO_EVENT
;
5959 if (pending_event_wait
.eventtype
== event
.type
)
5960 pending_event_wait
.eventtype
= 0; /* Indicates we got it. */
5966 if (event
.xclient
.message_type
5967 == dpyinfo
->Xatom_wm_protocols
5968 && event
.xclient
.format
== 32)
5970 if (event
.xclient
.data
.l
[0]
5971 == dpyinfo
->Xatom_wm_take_focus
)
5973 /* Use x_any_window_to_frame because this
5974 could be the shell widget window
5975 if the frame has no title bar. */
5976 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
5978 /* Not quite sure this is needed -pd */
5979 if (f
&& FRAME_XIC (f
))
5980 XSetICFocus (FRAME_XIC (f
));
5982 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5983 instructs the WM to set the input focus automatically for
5984 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5985 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5986 it has set the focus. So, XSetInputFocus below is not
5989 The call to XSetInputFocus below has also caused trouble. In
5990 cases where the XSetInputFocus done by the WM and the one
5991 below are temporally close (on a fast machine), the call
5992 below can generate additional FocusIn events which confuse
5995 /* Since we set WM_TAKE_FOCUS, we must call
5996 XSetInputFocus explicitly. But not if f is null,
5997 since that might be an event for a deleted frame. */
6000 Display
*d
= event
.xclient
.display
;
6001 /* Catch and ignore errors, in case window has been
6002 iconified by a window manager such as GWM. */
6004 XSetInputFocus (d
, event
.xclient
.window
,
6005 /* The ICCCM says this is
6006 the only valid choice. */
6008 event
.xclient
.data
.l
[1]);
6009 /* This is needed to detect the error
6010 if there is an error. */
6012 x_uncatch_errors ();
6014 /* Not certain about handling scroll bars here */
6019 if (event
.xclient
.data
.l
[0]
6020 == dpyinfo
->Xatom_wm_save_yourself
)
6022 /* Save state modify the WM_COMMAND property to
6023 something which can reinstate us. This notifies
6024 the session manager, who's looking for such a
6025 PropertyNotify. Can restart processing when
6026 a keyboard or mouse event arrives. */
6027 /* If we have a session manager, don't set this.
6028 KDE will then start two Emacsen, one for the
6029 session manager and one for this. */
6031 if (! x_session_have_connection ())
6034 f
= x_top_window_to_frame (dpyinfo
,
6035 event
.xclient
.window
);
6036 /* This is just so we only give real data once
6037 for a single Emacs process. */
6038 if (f
== SELECTED_FRAME ())
6039 XSetCommand (FRAME_X_DISPLAY (f
),
6040 event
.xclient
.window
,
6041 initial_argv
, initial_argc
);
6043 XSetCommand (FRAME_X_DISPLAY (f
),
6044 event
.xclient
.window
,
6050 if (event
.xclient
.data
.l
[0]
6051 == dpyinfo
->Xatom_wm_delete_window
)
6053 f
= x_any_window_to_frame (dpyinfo
,
6054 event
.xclient
.window
);
6056 goto OTHER
; /* May be a dialog that is to be removed */
6058 inev
.ie
.kind
= DELETE_WINDOW_EVENT
;
6059 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6066 if (event
.xclient
.message_type
6067 == dpyinfo
->Xatom_wm_configure_denied
)
6072 if (event
.xclient
.message_type
6073 == dpyinfo
->Xatom_wm_window_moved
)
6076 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
6078 new_x
= event
.xclient
.data
.s
[0];
6079 new_y
= event
.xclient
.data
.s
[1];
6083 f
->left_pos
= new_x
;
6090 if (event
.xclient
.message_type
6091 == dpyinfo
->Xatom_editres
)
6093 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
6095 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
6099 #endif /* HACK_EDITRES */
6101 if ((event
.xclient
.message_type
6102 == dpyinfo
->Xatom_DONE
)
6103 || (event
.xclient
.message_type
6104 == dpyinfo
->Xatom_PAGE
))
6106 /* Ghostview job completed. Kill it. We could
6107 reply with "Next" if we received "Page", but we
6108 currently never do because we are interested in
6109 images, only, which should have 1 page. */
6110 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
6111 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
6114 x_kill_gs_process (pixmap
, f
);
6115 expose_frame (f
, 0, 0, 0, 0);
6119 #ifdef USE_TOOLKIT_SCROLL_BARS
6120 /* Scroll bar callbacks send a ClientMessage from which
6121 we construct an input_event. */
6122 if (event
.xclient
.message_type
6123 == dpyinfo
->Xatom_Scrollbar
)
6125 x_scroll_bar_to_input_event (&event
, &inev
.ie
);
6126 *finish
= X_EVENT_GOTO_OUT
;
6129 #endif /* USE_TOOLKIT_SCROLL_BARS */
6131 /* XEmbed messages from the embedder (if any). */
6132 if (event
.xclient
.message_type
6133 == dpyinfo
->Xatom_XEMBED
)
6135 enum xembed_message msg
= event
.xclient
.data
.l
[1];
6136 if (msg
== XEMBED_FOCUS_IN
|| msg
== XEMBED_FOCUS_OUT
)
6137 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6139 *finish
= X_EVENT_GOTO_OUT
;
6143 xft_settings_event (dpyinfo
, &event
);
6145 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
6148 if (x_handle_dnd_message (f
, &event
.xclient
, dpyinfo
, &inev
.ie
))
6149 *finish
= X_EVENT_DROP
;
6153 case SelectionNotify
:
6154 last_user_time
= event
.xselection
.time
;
6155 #ifdef USE_X_TOOLKIT
6156 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
6158 #endif /* not USE_X_TOOLKIT */
6159 x_handle_selection_notify (&event
.xselection
);
6162 case SelectionClear
: /* Someone has grabbed ownership. */
6163 last_user_time
= event
.xselectionclear
.time
;
6164 #ifdef USE_X_TOOLKIT
6165 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
6167 #endif /* USE_X_TOOLKIT */
6169 XSelectionClearEvent
*eventp
= &(event
.xselectionclear
);
6171 inev
.ie
.kind
= SELECTION_CLEAR_EVENT
;
6172 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
6173 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
6174 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
6175 inev
.ie
.frame_or_window
= Qnil
;
6179 case SelectionRequest
: /* Someone wants our selection. */
6180 last_user_time
= event
.xselectionrequest
.time
;
6181 #ifdef USE_X_TOOLKIT
6182 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
6184 #endif /* USE_X_TOOLKIT */
6186 XSelectionRequestEvent
*eventp
= &(event
.xselectionrequest
);
6188 inev
.ie
.kind
= SELECTION_REQUEST_EVENT
;
6189 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
6190 SELECTION_EVENT_REQUESTOR (&inev
.sie
) = eventp
->requestor
;
6191 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
6192 SELECTION_EVENT_TARGET (&inev
.sie
) = eventp
->target
;
6193 SELECTION_EVENT_PROPERTY (&inev
.sie
) = eventp
->property
;
6194 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
6195 inev
.ie
.frame_or_window
= Qnil
;
6199 case PropertyNotify
:
6200 last_user_time
= event
.xproperty
.time
;
6201 f
= x_top_window_to_frame (dpyinfo
, event
.xproperty
.window
);
6202 if (f
&& event
.xproperty
.atom
== dpyinfo
->Xatom_net_wm_state
)
6203 if (x_handle_net_wm_state (f
, &event
.xproperty
) && f
->iconified
6204 && f
->output_data
.x
->net_wm_state_hidden_seen
)
6206 /* Gnome shell does not iconify us when C-z is pressed. It hides
6207 the frame. So if our state says we aren't hidden anymore,
6208 treat it as deiconified. */
6209 if (! f
->async_iconified
)
6210 SET_FRAME_GARBAGED (f
);
6211 f
->async_visible
= 1;
6212 f
->async_iconified
= 0;
6213 f
->output_data
.x
->has_been_visible
= 1;
6214 f
->output_data
.x
->net_wm_state_hidden_seen
= 0;
6215 inev
.ie
.kind
= DEICONIFY_EVENT
;
6216 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6219 x_handle_property_notify (&event
.xproperty
);
6220 xft_settings_event (dpyinfo
, &event
);
6223 case ReparentNotify
:
6224 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
6228 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
6229 x_real_positions (f
, &x
, &y
);
6233 /* Perhaps reparented due to a WM restart. Reset this. */
6234 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6235 FRAME_X_DISPLAY_INFO (f
)->net_supported_window
= 0;
6237 x_set_frame_alpha (f
);
6242 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
6246 /* This seems to be needed for GTK 2.6. */
6247 x_clear_area (event
.xexpose
.display
,
6248 event
.xexpose
.window
,
6249 event
.xexpose
.x
, event
.xexpose
.y
,
6250 event
.xexpose
.width
, event
.xexpose
.height
,
6253 if (f
->async_visible
== 0)
6255 f
->async_visible
= 1;
6256 f
->async_iconified
= 0;
6257 f
->output_data
.x
->has_been_visible
= 1;
6258 SET_FRAME_GARBAGED (f
);
6262 event
.xexpose
.x
, event
.xexpose
.y
,
6263 event
.xexpose
.width
, event
.xexpose
.height
);
6267 #ifndef USE_TOOLKIT_SCROLL_BARS
6268 struct scroll_bar
*bar
;
6270 #if defined USE_LUCID
6271 /* Submenus of the Lucid menu bar aren't widgets
6272 themselves, so there's no way to dispatch events
6273 to them. Recognize this case separately. */
6276 = x_window_to_menu_bar (event
.xexpose
.window
);
6278 xlwmenu_redisplay (widget
);
6280 #endif /* USE_LUCID */
6282 #ifdef USE_TOOLKIT_SCROLL_BARS
6283 /* Dispatch event to the widget. */
6285 #else /* not USE_TOOLKIT_SCROLL_BARS */
6286 bar
= x_window_to_scroll_bar (event
.xexpose
.display
,
6287 event
.xexpose
.window
);
6290 x_scroll_bar_expose (bar
, &event
);
6291 #ifdef USE_X_TOOLKIT
6294 #endif /* USE_X_TOOLKIT */
6295 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6299 case GraphicsExpose
: /* This occurs when an XCopyArea's
6300 source area was obscured or not
6302 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
6306 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
6307 event
.xgraphicsexpose
.width
,
6308 event
.xgraphicsexpose
.height
);
6310 #ifdef USE_X_TOOLKIT
6313 #endif /* USE_X_TOOLKIT */
6316 case NoExpose
: /* This occurs when an XCopyArea's
6317 source area was completely
6322 /* Redo the mouse-highlight after the tooltip has gone. */
6323 if (event
.xmap
.window
== tip_window
)
6326 redo_mouse_highlight ();
6329 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
6330 if (f
) /* F may no longer exist if
6331 the frame was deleted. */
6333 /* While a frame is unmapped, display generation is
6334 disabled; you don't want to spend time updating a
6335 display that won't ever be seen. */
6336 f
->async_visible
= 0;
6337 /* We can't distinguish, from the event, whether the window
6338 has become iconified or invisible. So assume, if it
6339 was previously visible, than now it is iconified.
6340 But x_make_frame_invisible clears both
6341 the visible flag and the iconified flag;
6342 and that way, we know the window is not iconified now. */
6343 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
6345 f
->async_iconified
= 1;
6347 inev
.ie
.kind
= ICONIFY_EVENT
;
6348 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6354 if (event
.xmap
.window
== tip_window
)
6355 /* The tooltip has been drawn already. Avoid
6356 the SET_FRAME_GARBAGED below. */
6359 /* We use x_top_window_to_frame because map events can
6360 come for sub-windows and they don't mean that the
6361 frame is visible. */
6362 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
6365 /* wait_reading_process_output will notice this and update
6366 the frame's display structures.
6367 If we where iconified, we should not set garbaged,
6368 because that stops redrawing on Expose events. This looks
6369 bad if we are called from a recursive event loop
6370 (x_dispatch_event), for example when a dialog is up. */
6371 if (! f
->async_iconified
)
6372 SET_FRAME_GARBAGED (f
);
6374 /* Check if fullscreen was specified before we where mapped the
6375 first time, i.e. from the command line. */
6376 if (!f
->output_data
.x
->has_been_visible
)
6377 x_check_fullscreen (f
);
6379 f
->async_visible
= 1;
6380 f
->async_iconified
= 0;
6381 f
->output_data
.x
->has_been_visible
= 1;
6385 inev
.ie
.kind
= DEICONIFY_EVENT
;
6386 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6388 else if (! NILP (Vframe_list
)
6389 && ! NILP (XCDR (Vframe_list
)))
6390 /* Force a redisplay sooner or later
6391 to update the frame titles
6392 in case this is the second frame. */
6393 record_asynch_buffer_change ();
6396 xg_frame_resized (f
, -1, -1);
6403 last_user_time
= event
.xkey
.time
;
6404 ignore_next_mouse_click_timeout
= 0;
6406 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6407 /* Dispatch KeyPress events when in menu. */
6408 if (popup_activated ())
6412 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
6414 /* If mouse-highlight is an integer, input clears out
6415 mouse highlighting. */
6416 if (!hlinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
6418 || !EQ (f
->tool_bar_window
, hlinfo
->mouse_face_window
)))
6420 clear_mouse_face (hlinfo
);
6421 hlinfo
->mouse_face_hidden
= 1;
6424 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6427 /* Scroll bars consume key events, but we want
6428 the keys to go to the scroll bar's frame. */
6429 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6431 if (widget
&& XmIsScrollBar (widget
))
6433 widget
= XtParent (widget
);
6434 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6437 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6441 KeySym keysym
, orig_keysym
;
6442 /* al%imercury@uunet.uu.net says that making this 81
6443 instead of 80 fixed a bug whereby meta chars made
6446 It seems that some version of XmbLookupString has
6447 a bug of not returning XBufferOverflow in
6448 status_return even if the input is too long to
6449 fit in 81 bytes. So, we must prepare sufficient
6450 bytes for copy_buffer. 513 bytes (256 chars for
6451 two-byte character set) seems to be a fairly good
6452 approximation. -- 2000.8.10 handa@etl.go.jp */
6453 unsigned char copy_buffer
[513];
6454 unsigned char *copy_bufptr
= copy_buffer
;
6455 int copy_bufsiz
= sizeof (copy_buffer
);
6457 Lisp_Object coding_system
= Qlatin_1
;
6461 /* Don't pass keys to GTK. A Tab will shift focus to the
6462 tool bar in GTK 2.4. Keys will still go to menus and
6463 dialogs because in that case popup_activated is TRUE
6465 *finish
= X_EVENT_DROP
;
6469 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
6470 extra_keyboard_modifiers
);
6471 modifiers
= event
.xkey
.state
;
6473 /* This will have to go some day... */
6475 /* make_lispy_event turns chars into control chars.
6476 Don't do it here because XLookupString is too eager. */
6477 event
.xkey
.state
&= ~ControlMask
;
6478 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6479 | dpyinfo
->super_mod_mask
6480 | dpyinfo
->hyper_mod_mask
6481 | dpyinfo
->alt_mod_mask
);
6483 /* In case Meta is ComposeCharacter,
6484 clear its status. According to Markus Ehrnsperger
6485 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6486 this enables ComposeCharacter to work whether or
6487 not it is combined with Meta. */
6488 if (modifiers
& dpyinfo
->meta_mod_mask
)
6489 memset (&compose_status
, 0, sizeof (compose_status
));
6494 Status status_return
;
6496 coding_system
= Vlocale_coding_system
;
6497 nbytes
= XmbLookupString (FRAME_XIC (f
),
6498 &event
.xkey
, (char *) copy_bufptr
,
6499 copy_bufsiz
, &keysym
,
6501 if (status_return
== XBufferOverflow
)
6503 copy_bufsiz
= nbytes
+ 1;
6504 copy_bufptr
= (unsigned char *) alloca (copy_bufsiz
);
6505 nbytes
= XmbLookupString (FRAME_XIC (f
),
6506 &event
.xkey
, (char *) copy_bufptr
,
6507 copy_bufsiz
, &keysym
,
6510 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6511 if (status_return
== XLookupNone
)
6513 else if (status_return
== XLookupChars
)
6518 else if (status_return
!= XLookupKeySym
6519 && status_return
!= XLookupBoth
)
6523 nbytes
= XLookupString (&event
.xkey
, (char *) copy_bufptr
,
6524 copy_bufsiz
, &keysym
,
6527 nbytes
= XLookupString (&event
.xkey
, (char *) copy_bufptr
,
6528 copy_bufsiz
, &keysym
,
6532 /* If not using XIM/XIC, and a compose sequence is in progress,
6533 we break here. Otherwise, chars_matched is always 0. */
6534 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6537 memset (&compose_status
, 0, sizeof (compose_status
));
6538 orig_keysym
= keysym
;
6540 /* Common for all keysym input events. */
6541 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6543 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), modifiers
);
6544 inev
.ie
.timestamp
= event
.xkey
.time
;
6546 /* First deal with keysyms which have defined
6547 translations to characters. */
6548 if (keysym
>= 32 && keysym
< 128)
6549 /* Avoid explicitly decoding each ASCII character. */
6551 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6552 inev
.ie
.code
= keysym
;
6556 /* Keysyms directly mapped to Unicode characters. */
6557 if (keysym
>= 0x01000000 && keysym
<= 0x0110FFFF)
6559 if (keysym
< 0x01000080)
6560 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6562 inev
.ie
.kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
6563 inev
.ie
.code
= keysym
& 0xFFFFFF;
6567 /* Now non-ASCII. */
6568 if (HASH_TABLE_P (Vx_keysym_table
)
6569 && (c
= Fgethash (make_number (keysym
),
6574 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6575 ? ASCII_KEYSTROKE_EVENT
6576 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6577 inev
.ie
.code
= XFASTINT (c
);
6581 /* Random non-modifier sorts of keysyms. */
6582 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6583 || keysym
== XK_Delete
6584 #ifdef XK_ISO_Left_Tab
6585 || (keysym
>= XK_ISO_Left_Tab
6586 && keysym
<= XK_ISO_Enter
)
6588 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6589 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6591 /* This recognizes the "extended function
6592 keys". It seems there's no cleaner way.
6593 Test IsModifierKey to avoid handling
6594 mode_switch incorrectly. */
6595 || (XK_Select
<= keysym
&& keysym
< XK_KP_Space
)
6597 #ifdef XK_dead_circumflex
6598 || orig_keysym
== XK_dead_circumflex
6600 #ifdef XK_dead_grave
6601 || orig_keysym
== XK_dead_grave
6603 #ifdef XK_dead_tilde
6604 || orig_keysym
== XK_dead_tilde
6606 #ifdef XK_dead_diaeresis
6607 || orig_keysym
== XK_dead_diaeresis
6609 #ifdef XK_dead_macron
6610 || orig_keysym
== XK_dead_macron
6612 #ifdef XK_dead_degree
6613 || orig_keysym
== XK_dead_degree
6615 #ifdef XK_dead_acute
6616 || orig_keysym
== XK_dead_acute
6618 #ifdef XK_dead_cedilla
6619 || orig_keysym
== XK_dead_cedilla
6621 #ifdef XK_dead_breve
6622 || orig_keysym
== XK_dead_breve
6624 #ifdef XK_dead_ogonek
6625 || orig_keysym
== XK_dead_ogonek
6627 #ifdef XK_dead_caron
6628 || orig_keysym
== XK_dead_caron
6630 #ifdef XK_dead_doubleacute
6631 || orig_keysym
== XK_dead_doubleacute
6633 #ifdef XK_dead_abovedot
6634 || orig_keysym
== XK_dead_abovedot
6636 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6637 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6638 /* Any "vendor-specific" key is ok. */
6639 || (orig_keysym
& (1 << 28))
6640 || (keysym
!= NoSymbol
&& nbytes
== 0))
6641 && ! (IsModifierKey (orig_keysym
)
6642 /* The symbols from XK_ISO_Lock
6643 to XK_ISO_Last_Group_Lock
6644 don't have real modifiers but
6645 should be treated similarly to
6646 Mode_switch by Emacs. */
6647 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6648 || (XK_ISO_Lock
<= orig_keysym
6649 && orig_keysym
<= XK_ISO_Last_Group_Lock
)
6653 STORE_KEYSYM_FOR_DEBUG (keysym
);
6654 /* make_lispy_event will convert this to a symbolic
6656 inev
.ie
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6657 inev
.ie
.code
= keysym
;
6661 { /* Raw bytes, not keysym. */
6665 for (i
= 0, nchars
= 0; i
< nbytes
; i
++)
6667 if (ASCII_BYTE_P (copy_bufptr
[i
]))
6669 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6672 if (nchars
< nbytes
)
6674 /* Decode the input data. */
6676 /* The input should be decoded with `coding_system'
6677 which depends on which X*LookupString function
6678 we used just above and the locale. */
6679 setup_coding_system (coding_system
, &coding
);
6680 coding
.src_multibyte
= 0;
6681 coding
.dst_multibyte
= 1;
6682 /* The input is converted to events, thus we can't
6683 handle composition. Anyway, there's no XIM that
6684 gives us composition information. */
6685 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
6687 SAFE_NALLOCA (coding
.destination
, MAX_MULTIBYTE_LENGTH
,
6689 coding
.dst_bytes
= MAX_MULTIBYTE_LENGTH
* nbytes
;
6690 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6691 decode_coding_c_string (&coding
, copy_bufptr
, nbytes
, Qnil
);
6692 nbytes
= coding
.produced
;
6693 nchars
= coding
.produced_char
;
6694 copy_bufptr
= coding
.destination
;
6697 /* Convert the input data to a sequence of
6698 character events. */
6699 for (i
= 0; i
< nbytes
; i
+= len
)
6702 if (nchars
== nbytes
)
6703 ch
= copy_bufptr
[i
], len
= 1;
6705 ch
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
, len
);
6706 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (ch
)
6707 ? ASCII_KEYSTROKE_EVENT
6708 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6710 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
6715 inev
.ie
.kind
= NO_EVENT
; /* Already stored above. */
6717 if (keysym
== NoSymbol
)
6723 /* Don't dispatch this event since XtDispatchEvent calls
6724 XFilterEvent, and two calls in a row may freeze the
6732 last_user_time
= event
.xkey
.time
;
6734 /* Don't dispatch this event since XtDispatchEvent calls
6735 XFilterEvent, and two calls in a row may freeze the
6743 last_user_time
= event
.xcrossing
.time
;
6744 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6746 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6748 if (f
&& x_mouse_click_focus_ignore_position
)
6749 ignore_next_mouse_click_timeout
= event
.xmotion
.time
+ 200;
6751 /* EnterNotify counts as mouse movement,
6752 so update things that depend on mouse position. */
6753 if (f
&& !f
->output_data
.x
->hourglass_p
)
6754 note_mouse_movement (f
, &event
.xmotion
);
6756 /* We may get an EnterNotify on the buttons in the toolbar. In that
6757 case we moved out of any highlighted area and need to note this. */
6758 if (!f
&& last_mouse_glyph_frame
)
6759 note_mouse_movement (last_mouse_glyph_frame
, &event
.xmotion
);
6764 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6768 last_user_time
= event
.xcrossing
.time
;
6769 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6771 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
6774 if (f
== hlinfo
->mouse_face_mouse_frame
)
6776 /* If we move outside the frame, then we're
6777 certainly no longer on any text in the frame. */
6778 clear_mouse_face (hlinfo
);
6779 hlinfo
->mouse_face_mouse_frame
= 0;
6782 /* Generate a nil HELP_EVENT to cancel a help-echo.
6783 Do it only if there's something to cancel.
6784 Otherwise, the startup message is cleared when
6785 the mouse leaves the frame. */
6786 if (any_help_event_p
)
6790 /* See comment in EnterNotify above */
6791 else if (last_mouse_glyph_frame
)
6792 note_mouse_movement (last_mouse_glyph_frame
, &event
.xmotion
);
6797 x_detect_focus_change (dpyinfo
, &event
, &inev
.ie
);
6802 last_user_time
= event
.xmotion
.time
;
6803 previous_help_echo_string
= help_echo_string
;
6804 help_echo_string
= Qnil
;
6806 if (dpyinfo
->grabbed
&& last_mouse_frame
6807 && FRAME_LIVE_P (last_mouse_frame
))
6808 f
= last_mouse_frame
;
6810 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
6812 if (hlinfo
->mouse_face_hidden
)
6814 hlinfo
->mouse_face_hidden
= 0;
6815 clear_mouse_face (hlinfo
);
6819 if (f
&& xg_event_is_for_scrollbar (f
, &event
))
6825 /* Generate SELECT_WINDOW_EVENTs when needed.
6826 Don't let popup menus influence things (bug#1261). */
6827 if (!NILP (Vmouse_autoselect_window
) && !popup_activated ())
6831 window
= window_from_coordinates (f
,
6832 event
.xmotion
.x
, event
.xmotion
.y
,
6835 /* Window will be selected only when it is not selected now and
6836 last mouse movement event was not in it. Minibuffer window
6837 will be selected only when it is active. */
6838 if (WINDOWP (window
)
6839 && !EQ (window
, last_window
)
6840 && !EQ (window
, selected_window
)
6841 /* For click-to-focus window managers
6842 create event iff we don't leave the
6844 && (focus_follows_mouse
6845 || (EQ (XWINDOW (window
)->frame
,
6846 XWINDOW (selected_window
)->frame
))))
6848 inev
.ie
.kind
= SELECT_WINDOW_EVENT
;
6849 inev
.ie
.frame_or_window
= window
;
6854 if (!note_mouse_movement (f
, &event
.xmotion
))
6855 help_echo_string
= previous_help_echo_string
;
6859 #ifndef USE_TOOLKIT_SCROLL_BARS
6860 struct scroll_bar
*bar
6861 = x_window_to_scroll_bar (event
.xmotion
.display
,
6862 event
.xmotion
.window
);
6865 x_scroll_bar_note_movement (bar
, &event
);
6866 #endif /* USE_TOOLKIT_SCROLL_BARS */
6868 /* If we move outside the frame, then we're
6869 certainly no longer on any text in the frame. */
6870 clear_mouse_face (hlinfo
);
6873 /* If the contents of the global variable help_echo_string
6874 has changed, generate a HELP_EVENT. */
6875 if (!NILP (help_echo_string
)
6876 || !NILP (previous_help_echo_string
))
6881 case ConfigureNotify
:
6882 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
6885 && (f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
))
6886 && event
.xconfigure
.window
== FRAME_X_WINDOW (f
))
6888 xg_frame_resized (f
, event
.xconfigure
.width
,
6889 event
.xconfigure
.height
);
6895 #ifndef USE_X_TOOLKIT
6897 int rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, event
.xconfigure
.height
);
6898 int columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, event
.xconfigure
.width
);
6900 /* In the toolkit version, change_frame_size
6901 is called by the code that handles resizing
6902 of the EmacsFrame widget. */
6904 /* Even if the number of character rows and columns has
6905 not changed, the font size may have changed, so we need
6906 to check the pixel dimensions as well. */
6907 if (columns
!= FRAME_COLS (f
)
6908 || rows
!= FRAME_LINES (f
)
6909 || event
.xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6910 || event
.xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6912 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6913 SET_FRAME_GARBAGED (f
);
6914 cancel_mouse_face (f
);
6917 FRAME_PIXEL_WIDTH (f
) = event
.xconfigure
.width
;
6918 FRAME_PIXEL_HEIGHT (f
) = event
.xconfigure
.height
;
6919 #endif /* not USE_GTK */
6923 /* GTK creates windows but doesn't map them.
6924 Only get real positions when mapped. */
6925 if (FRAME_GTK_OUTER_WIDGET (f
)
6926 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f
)))
6929 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6933 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6934 xic_set_statusarea (f
);
6943 /* If we decide we want to generate an event to be seen
6944 by the rest of Emacs, we put it here. */
6947 memset (&compose_status
, 0, sizeof (compose_status
));
6948 last_mouse_glyph_frame
= 0;
6949 last_user_time
= event
.xbutton
.time
;
6951 if (dpyinfo
->grabbed
6953 && FRAME_LIVE_P (last_mouse_frame
))
6954 f
= last_mouse_frame
;
6956 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
6959 if (f
&& xg_event_is_for_scrollbar (f
, &event
))
6964 /* Is this in the tool-bar? */
6965 if (WINDOWP (f
->tool_bar_window
)
6966 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6969 int x
= event
.xbutton
.x
;
6970 int y
= event
.xbutton
.y
;
6972 window
= window_from_coordinates (f
, x
, y
, 0, 1);
6973 tool_bar_p
= EQ (window
, f
->tool_bar_window
);
6975 if (tool_bar_p
&& event
.xbutton
.button
< 4)
6977 handle_tool_bar_click (f
, x
, y
,
6978 event
.xbutton
.type
== ButtonPress
,
6979 x_x_to_emacs_modifiers (dpyinfo
,
6980 event
.xbutton
.state
));
6985 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6986 if (! popup_activated ())
6989 if (ignore_next_mouse_click_timeout
)
6991 if (event
.type
== ButtonPress
6992 && (int)(event
.xbutton
.time
- ignore_next_mouse_click_timeout
) > 0)
6994 ignore_next_mouse_click_timeout
= 0;
6995 construct_mouse_click (&inev
.ie
, &event
.xbutton
, f
);
6997 if (event
.type
== ButtonRelease
)
6998 ignore_next_mouse_click_timeout
= 0;
7001 construct_mouse_click (&inev
.ie
, &event
.xbutton
, f
);
7003 if (FRAME_X_EMBEDDED_P (f
))
7004 xembed_send_message (f
, event
.xbutton
.time
,
7005 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
7009 struct scroll_bar
*bar
7010 = x_window_to_scroll_bar (event
.xbutton
.display
,
7011 event
.xbutton
.window
);
7013 #ifdef USE_TOOLKIT_SCROLL_BARS
7014 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
7016 if (bar
&& event
.xbutton
.state
& ControlMask
)
7018 x_scroll_bar_handle_click (bar
, &event
, &inev
.ie
);
7019 *finish
= X_EVENT_DROP
;
7021 #else /* not USE_TOOLKIT_SCROLL_BARS */
7023 x_scroll_bar_handle_click (bar
, &event
, &inev
.ie
);
7024 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7027 if (event
.type
== ButtonPress
)
7029 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
7030 last_mouse_frame
= f
;
7033 last_tool_bar_item
= -1;
7036 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
7038 /* Ignore any mouse motion that happened before this event;
7039 any subsequent mouse-movement Emacs events should reflect
7040 only motion after the ButtonPress/Release. */
7044 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
7045 f
= x_menubar_window_to_frame (dpyinfo
, &event
);
7046 /* For a down-event in the menu bar,
7047 don't pass it to Xt right now.
7048 Instead, save it away
7049 and we will pass it to Xt from kbd_buffer_get_event.
7050 That way, we can run some Lisp code first. */
7051 if (! popup_activated ()
7053 /* Gtk+ menus only react to the first three buttons. */
7054 && event
.xbutton
.button
< 3
7056 && f
&& event
.type
== ButtonPress
7057 /* Verify the event is really within the menu bar
7058 and not just sent to it due to grabbing. */
7059 && event
.xbutton
.x
>= 0
7060 && event
.xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
7061 && event
.xbutton
.y
>= 0
7062 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
7063 && event
.xbutton
.same_screen
)
7065 SET_SAVED_BUTTON_EVENT
;
7066 XSETFRAME (last_mouse_press_frame
, f
);
7067 *finish
= X_EVENT_DROP
;
7069 else if (event
.type
== ButtonPress
)
7071 last_mouse_press_frame
= Qnil
;
7076 #endif /* USE_X_TOOLKIT || USE_GTK */
7080 case CirculateNotify
:
7083 case CirculateRequest
:
7086 case VisibilityNotify
:
7090 /* Someone has changed the keyboard mapping - update the
7092 switch (event
.xmapping
.request
)
7094 case MappingModifier
:
7095 x_find_modifier_meanings (dpyinfo
);
7096 /* This is meant to fall through. */
7097 case MappingKeyboard
:
7098 XRefreshKeyboardMapping (&event
.xmapping
);
7103 xft_settings_event (dpyinfo
, &event
);
7108 #ifdef USE_X_TOOLKIT
7110 if (*finish
!= X_EVENT_DROP
)
7111 XtDispatchEvent (&event
);
7113 #endif /* USE_X_TOOLKIT */
7118 if (inev
.ie
.kind
!= NO_EVENT
)
7120 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
7125 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
7130 XSETFRAME (frame
, f
);
7136 any_help_event_p
= 1;
7137 gen_help_event (help_echo_string
, frame
, help_echo_window
,
7138 help_echo_object
, help_echo_pos
);
7142 help_echo_string
= Qnil
;
7143 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
7153 #if defined USE_GTK || defined USE_X_TOOLKIT
7155 /* Handles the XEvent EVENT on display DISPLAY.
7156 This is used for event loops outside the normal event handling,
7157 i.e. looping while a popup menu or a dialog is posted.
7159 Returns the value handle_one_xevent sets in the finish argument. */
7161 x_dispatch_event (XEvent
*event
, Display
*display
)
7163 struct x_display_info
*dpyinfo
;
7164 int finish
= X_EVENT_NORMAL
;
7166 dpyinfo
= x_display_info_for_display (display
);
7169 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
7176 /* Read events coming from the X server.
7177 This routine is called by the SIGIO handler only if SYNC_INPUT is
7179 We return as soon as there are no more events to be read.
7181 We return the number of characters stored into the buffer,
7182 thus pretending to be `read' (except the characters we store
7183 in the keyboard buffer can be multibyte, so are not necessarily
7186 EXPECTED is nonzero if the caller knows input is available. */
7189 XTread_socket (struct terminal
*terminal
, int expected
, struct input_event
*hold_quit
)
7192 int event_found
= 0;
7194 if (interrupt_input_blocked
)
7196 interrupt_input_pending
= 1;
7198 pending_signals
= 1;
7203 interrupt_input_pending
= 0;
7205 pending_signals
= pending_atimers
;
7209 /* So people can tell when we have read the available input. */
7210 input_signal_count
++;
7216 /* For debugging, this gives a way to fake an I/O error. */
7217 if (terminal
->display_info
.x
== XTread_socket_fake_io_error
)
7219 XTread_socket_fake_io_error
= 0;
7220 x_io_error_quitter (terminal
->display_info
.x
->display
);
7224 while (XPending (terminal
->display_info
.x
->display
))
7229 XNextEvent (terminal
->display_info
.x
->display
, &event
);
7232 /* Filter events for the current X input method. */
7233 if (x_filter_event (terminal
->display_info
.x
, &event
))
7238 count
+= handle_one_xevent (terminal
->display_info
.x
,
7239 &event
, &finish
, hold_quit
);
7241 if (finish
== X_EVENT_GOTO_OUT
)
7249 /* For GTK we must use the GTK event loop. But XEvents gets passed
7250 to our filter function above, and then to the big event switch.
7251 We use a bunch of globals to communicate with our filter function,
7252 that is kind of ugly, but it works.
7254 There is no way to do one display at the time, GTK just does events
7255 from all displays. */
7257 while (gtk_events_pending ())
7259 current_count
= count
;
7260 current_hold_quit
= hold_quit
;
7262 gtk_main_iteration ();
7264 count
= current_count
;
7266 current_hold_quit
= 0;
7268 if (current_finish
== X_EVENT_GOTO_OUT
)
7271 #endif /* USE_GTK */
7273 /* On some systems, an X bug causes Emacs to get no more events
7274 when the window is destroyed. Detect that. (1994.) */
7277 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7278 One XNOOP in 100 loops will make Emacs terminate.
7279 B. Bretthauer, 1994 */
7281 if (x_noop_count
>= 100)
7285 if (next_noop_dpyinfo
== 0)
7286 next_noop_dpyinfo
= x_display_list
;
7288 XNoOp (next_noop_dpyinfo
->display
);
7290 /* Each time we get here, cycle through the displays now open. */
7291 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7295 /* If the focus was just given to an auto-raising frame,
7297 /* ??? This ought to be able to handle more than one such frame. */
7298 if (pending_autoraise_frame
)
7300 x_raise_frame (pending_autoraise_frame
);
7301 pending_autoraise_frame
= 0;
7315 /***********************************************************************
7317 ***********************************************************************/
7319 /* Set clipping for output in glyph row ROW. W is the window in which
7320 we operate. GC is the graphics context to set clipping in.
7322 ROW may be a text row or, e.g., a mode line. Text rows must be
7323 clipped to the interior of the window dedicated to text display,
7324 mode lines must be clipped to the whole window. */
7327 x_clip_to_row (struct window
*w
, struct glyph_row
*row
, int area
, GC gc
)
7329 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7330 XRectangle clip_rect
;
7331 int window_x
, window_y
, window_width
;
7333 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
7335 clip_rect
.x
= window_x
;
7336 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, row
->y
));
7337 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7338 clip_rect
.width
= window_width
;
7339 clip_rect
.height
= row
->visible_height
;
7341 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7345 /* Draw a hollow box cursor on window W in glyph row ROW. */
7348 x_draw_hollow_cursor (struct window
*w
, struct glyph_row
*row
)
7350 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7351 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7352 Display
*dpy
= FRAME_X_DISPLAY (f
);
7355 struct glyph
*cursor_glyph
;
7358 /* Get the glyph the cursor is on. If we can't tell because
7359 the current matrix is invalid or such, give up. */
7360 cursor_glyph
= get_phys_cursor_glyph (w
);
7361 if (cursor_glyph
== NULL
)
7364 /* Compute frame-relative coordinates for phys cursor. */
7365 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
7366 wd
= w
->phys_cursor_width
;
7368 /* The foreground of cursor_gc is typically the same as the normal
7369 background color, which can cause the cursor box to be invisible. */
7370 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7371 if (dpyinfo
->scratch_cursor_gc
)
7372 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7374 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7375 GCForeground
, &xgcv
);
7376 gc
= dpyinfo
->scratch_cursor_gc
;
7378 /* Set clipping, draw the rectangle, and reset clipping again. */
7379 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7380 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
- 1);
7381 XSetClipMask (dpy
, gc
, None
);
7385 /* Draw a bar cursor on window W in glyph row ROW.
7387 Implementation note: One would like to draw a bar cursor with an
7388 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7389 Unfortunately, I didn't find a font yet that has this property set.
7393 x_draw_bar_cursor (struct window
*w
, struct glyph_row
*row
, int width
, enum text_cursor_kinds kind
)
7395 struct frame
*f
= XFRAME (w
->frame
);
7396 struct glyph
*cursor_glyph
;
7398 /* If cursor is out of bounds, don't draw garbage. This can happen
7399 in mini-buffer windows when switching between echo area glyphs
7401 cursor_glyph
= get_phys_cursor_glyph (w
);
7402 if (cursor_glyph
== NULL
)
7405 /* If on an image, draw like a normal cursor. That's usually better
7406 visible than drawing a bar, esp. if the image is large so that
7407 the bar might not be in the window. */
7408 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7410 struct glyph_row
*r
;
7411 r
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7412 draw_phys_cursor_glyph (w
, r
, DRAW_CURSOR
);
7416 Display
*dpy
= FRAME_X_DISPLAY (f
);
7417 Window window
= FRAME_X_WINDOW (f
);
7418 GC gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7419 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7420 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7423 /* If the glyph's background equals the color we normally draw
7424 the bars cursor in, the bar cursor in its normal color is
7425 invisible. Use the glyph's foreground color instead in this
7426 case, on the assumption that the glyph's colors are chosen so
7427 that the glyph is legible. */
7428 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7429 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7431 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7432 xgcv
.graphics_exposures
= 0;
7435 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7438 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7439 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7442 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7444 if (kind
== BAR_CURSOR
)
7446 int x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7449 width
= FRAME_CURSOR_WIDTH (f
);
7450 width
= min (cursor_glyph
->pixel_width
, width
);
7452 w
->phys_cursor_width
= width
;
7454 /* If the character under cursor is R2L, draw the bar cursor
7455 on the right of its glyph, rather than on the left. */
7456 if ((cursor_glyph
->resolved_level
& 1) != 0)
7457 x
+= cursor_glyph
->pixel_width
- width
;
7459 XFillRectangle (dpy
, window
, gc
, x
,
7460 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7461 width
, row
->height
);
7465 int dummy_x
, dummy_y
, dummy_h
;
7468 width
= row
->height
;
7470 width
= min (row
->height
, width
);
7472 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &dummy_x
,
7473 &dummy_y
, &dummy_h
);
7475 XFillRectangle (dpy
, window
, gc
,
7476 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7477 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7478 row
->height
- width
),
7479 w
->phys_cursor_width
, width
);
7482 XSetClipMask (dpy
, gc
, None
);
7487 /* RIF: Define cursor CURSOR on frame F. */
7490 x_define_frame_cursor (struct frame
*f
, Cursor cursor
)
7492 if (!f
->pointer_invisible
7493 && f
->output_data
.x
->current_cursor
!= cursor
)
7494 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7495 f
->output_data
.x
->current_cursor
= cursor
;
7499 /* RIF: Clear area on frame F. */
7502 x_clear_frame_area (struct frame
*f
, int x
, int y
, int width
, int height
)
7504 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7505 x
, y
, width
, height
, False
);
7507 /* Must queue a redraw, because scroll bars might have been cleared. */
7508 if (FRAME_GTK_WIDGET (f
))
7509 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
7514 /* RIF: Draw cursor on window W. */
7517 x_draw_window_cursor (struct window
*w
, struct glyph_row
*glyph_row
, int x
, int y
, int cursor_type
, int cursor_width
, int on_p
, int active_p
)
7519 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7523 w
->phys_cursor_type
= cursor_type
;
7524 w
->phys_cursor_on_p
= 1;
7526 if (glyph_row
->exact_window_width_line_p
7527 && (glyph_row
->reversed_p
7528 ? (w
->phys_cursor
.hpos
< 0)
7529 : (w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])))
7531 glyph_row
->cursor_in_fringe_p
= 1;
7532 draw_fringe_bitmap (w
, glyph_row
, glyph_row
->reversed_p
);
7536 switch (cursor_type
)
7538 case HOLLOW_BOX_CURSOR
:
7539 x_draw_hollow_cursor (w
, glyph_row
);
7542 case FILLED_BOX_CURSOR
:
7543 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7547 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7551 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7555 w
->phys_cursor_width
= 0;
7564 if (w
== XWINDOW (f
->selected_window
))
7565 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7566 xic_set_preeditarea (w
, x
, y
);
7571 XFlush (FRAME_X_DISPLAY (f
));
7578 /* Make the x-window of frame F use the gnu icon bitmap. */
7581 x_bitmap_icon (struct frame
*f
, Lisp_Object file
)
7583 ptrdiff_t bitmap_id
;
7585 if (FRAME_X_WINDOW (f
) == 0)
7588 /* Free up our existing icon bitmap and mask if any. */
7589 if (f
->output_data
.x
->icon_bitmap
> 0)
7590 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7591 f
->output_data
.x
->icon_bitmap
= 0;
7596 /* Use gtk_window_set_icon_from_file () if available,
7597 It's not restricted to bitmaps */
7598 if (xg_set_icon (f
, file
))
7600 #endif /* USE_GTK */
7601 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7602 x_create_bitmap_mask (f
, bitmap_id
);
7606 /* Create the GNU bitmap and mask if necessary. */
7607 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7613 if (xg_set_icon (f
, xg_default_icon_file
)
7614 || xg_set_icon_from_xpm_data (f
, gnu_xpm_bits
))
7617 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7619 rc
= x_create_bitmap_from_xpm_data (f
, gnu_xpm_bits
);
7621 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7625 /* If all else fails, use the (black and white) xbm image. */
7628 rc
= x_create_bitmap_from_data (f
, (char *) gnu_xbm_bits
,
7629 gnu_xbm_width
, gnu_xbm_height
);
7633 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7634 x_create_bitmap_mask (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7638 /* The first time we create the GNU bitmap and mask,
7639 this increments the ref-count one extra time.
7640 As a result, the GNU bitmap and mask are never freed.
7641 That way, we don't have to worry about allocating it again. */
7642 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
7644 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
7647 x_wm_set_icon_pixmap (f
, bitmap_id
);
7648 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7654 /* Make the x-window of frame F use a rectangle with text.
7655 Use ICON_NAME as the text. */
7658 x_text_icon (struct frame
*f
, const char *icon_name
)
7660 if (FRAME_X_WINDOW (f
) == 0)
7665 text
.value
= (unsigned char *) icon_name
;
7666 text
.encoding
= XA_STRING
;
7668 text
.nitems
= strlen (icon_name
);
7669 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7672 if (f
->output_data
.x
->icon_bitmap
> 0)
7673 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7674 f
->output_data
.x
->icon_bitmap
= 0;
7675 x_wm_set_icon_pixmap (f
, 0);
7680 #define X_ERROR_MESSAGE_SIZE 200
7682 /* If non-nil, this should be a string.
7683 It means catch X errors and store the error message in this string.
7685 The reason we use a stack is that x_catch_error/x_uncatch_error can
7686 be called from a signal handler.
7689 struct x_error_message_stack
{
7690 char string
[X_ERROR_MESSAGE_SIZE
];
7692 struct x_error_message_stack
*prev
;
7694 static struct x_error_message_stack
*x_error_message
;
7696 /* An X error handler which stores the error message in
7697 *x_error_message. This is called from x_error_handler if
7698 x_catch_errors is in effect. */
7701 x_error_catcher (Display
*display
, XErrorEvent
*event
)
7703 XGetErrorText (display
, event
->error_code
,
7704 x_error_message
->string
,
7705 X_ERROR_MESSAGE_SIZE
);
7708 /* Begin trapping X errors for display DPY. Actually we trap X errors
7709 for all displays, but DPY should be the display you are actually
7712 After calling this function, X protocol errors no longer cause
7713 Emacs to exit; instead, they are recorded in the string
7714 stored in *x_error_message.
7716 Calling x_check_errors signals an Emacs error if an X error has
7717 occurred since the last call to x_catch_errors or x_check_errors.
7719 Calling x_uncatch_errors resumes the normal error handling. */
7722 x_catch_errors (Display
*dpy
)
7724 struct x_error_message_stack
*data
= xmalloc (sizeof (*data
));
7726 /* Make sure any errors from previous requests have been dealt with. */
7730 data
->string
[0] = 0;
7731 data
->prev
= x_error_message
;
7732 x_error_message
= data
;
7735 /* Undo the last x_catch_errors call.
7736 DPY should be the display that was passed to x_catch_errors. */
7739 x_uncatch_errors (void)
7741 struct x_error_message_stack
*tmp
;
7745 /* The display may have been closed before this function is called.
7746 Check if it is still open before calling XSync. */
7747 if (x_display_info_for_display (x_error_message
->dpy
) != 0)
7748 XSync (x_error_message
->dpy
, False
);
7750 tmp
= x_error_message
;
7751 x_error_message
= x_error_message
->prev
;
7756 /* If any X protocol errors have arrived since the last call to
7757 x_catch_errors or x_check_errors, signal an Emacs error using
7758 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7761 x_check_errors (Display
*dpy
, const char *format
)
7763 /* Make sure to catch any errors incurred so far. */
7766 if (x_error_message
->string
[0])
7768 char string
[X_ERROR_MESSAGE_SIZE
];
7769 memcpy (string
, x_error_message
->string
, X_ERROR_MESSAGE_SIZE
);
7770 x_uncatch_errors ();
7771 error (format
, string
);
7775 /* Nonzero if we had any X protocol errors
7776 since we did x_catch_errors on DPY. */
7779 x_had_errors_p (Display
*dpy
)
7781 /* Make sure to catch any errors incurred so far. */
7784 return x_error_message
->string
[0] != 0;
7787 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7790 x_clear_errors (Display
*dpy
)
7792 x_error_message
->string
[0] = 0;
7795 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7796 * idea. --lorentey */
7797 /* Close off all unclosed x_catch_errors calls. */
7800 x_fully_uncatch_errors (void)
7802 while (x_error_message
)
7803 x_uncatch_errors ();
7808 static unsigned int x_wire_count
;
7811 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7816 /* Handle SIGPIPE, which can happen when the connection to a server
7817 simply goes away. SIGPIPE is handled by x_connection_signal.
7818 Don't need to do anything, because the write which caused the
7819 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7820 which will do the appropriate cleanup for us. */
7823 x_connection_signal (int signalnum
) /* If we don't have an argument, */
7824 /* some compilers complain in signal calls. */
7827 /* USG systems forget handlers when they are used;
7828 must reestablish each time */
7829 signal (signalnum
, x_connection_signal
);
7834 /************************************************************************
7836 ************************************************************************/
7838 /* Error message passed to x_connection_closed. */
7840 static char *error_msg
;
7842 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7843 the text of an error message that lead to the connection loss. */
7846 x_connection_closed (Display
*dpy
, const char *error_message
)
7848 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7849 Lisp_Object frame
, tail
;
7850 ptrdiff_t idx
= SPECPDL_INDEX ();
7852 error_msg
= (char *) alloca (strlen (error_message
) + 1);
7853 strcpy (error_msg
, error_message
);
7854 handling_signal
= 0;
7856 /* Inhibit redisplay while frames are being deleted. */
7857 specbind (Qinhibit_redisplay
, Qt
);
7861 /* Protect display from being closed when we delete the last
7863 dpyinfo
->reference_count
++;
7864 dpyinfo
->terminal
->reference_count
++;
7867 /* First delete frames whose mini-buffers are on frames
7868 that are on the dead display. */
7869 FOR_EACH_FRAME (tail
, frame
)
7871 Lisp_Object minibuf_frame
;
7873 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7874 if (FRAME_X_P (XFRAME (frame
))
7875 && FRAME_X_P (XFRAME (minibuf_frame
))
7876 && ! EQ (frame
, minibuf_frame
)
7877 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7878 delete_frame (frame
, Qnoelisp
);
7881 /* Now delete all remaining frames on the dead display.
7882 We are now sure none of these is used as the mini-buffer
7883 for another frame that we need to delete. */
7884 FOR_EACH_FRAME (tail
, frame
)
7885 if (FRAME_X_P (XFRAME (frame
))
7886 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7888 /* Set this to t so that delete_frame won't get confused
7889 trying to find a replacement. */
7890 KVAR (FRAME_KBOARD (XFRAME (frame
)), Vdefault_minibuffer_frame
) = Qt
;
7891 delete_frame (frame
, Qnoelisp
);
7894 /* If DPYINFO is null, this means we didn't open the display in the
7895 first place, so don't try to close it. */
7898 /* We can not call XtCloseDisplay here because it calls XSync.
7899 XSync inside the error handler apparently hangs Emacs. On
7900 current Xt versions, this isn't needed either. */
7902 /* A long-standing GTK bug prevents proper disconnect handling
7903 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
7904 the resulting Glib error message loop filled a user's disk.
7905 To avoid this, kill Emacs unconditionally on disconnect. */
7906 shut_down_emacs (0, 0, Qnil
);
7907 fprintf (stderr
, "%s\n\
7908 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
7909 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
7910 For details, see etc/PROBLEMS.\n",
7913 #endif /* USE_GTK */
7915 /* Indicate that this display is dead. */
7916 dpyinfo
->display
= 0;
7918 dpyinfo
->reference_count
--;
7919 dpyinfo
->terminal
->reference_count
--;
7920 if (dpyinfo
->reference_count
!= 0)
7921 /* We have just closed all frames on this display. */
7926 XSETTERMINAL (tmp
, dpyinfo
->terminal
);
7927 Fdelete_terminal (tmp
, Qnoelisp
);
7931 if (terminal_list
== 0)
7933 fprintf (stderr
, "%s\n", error_msg
);
7934 Fkill_emacs (make_number (70));
7938 /* Ordinary stack unwind doesn't deal with these. */
7940 sigunblock (sigmask (SIGIO
));
7942 sigunblock (sigmask (SIGALRM
));
7943 TOTALLY_UNBLOCK_INPUT
;
7945 unbind_to (idx
, Qnil
);
7946 clear_waiting_for_input ();
7948 /* Tell GCC not to suggest attribute 'noreturn' for this function. */
7949 IF_LINT (if (! terminal_list
) return; )
7951 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7952 longjmp), because returning from this function would get us back into
7953 Xlib's code which will directly call `exit'. */
7954 error ("%s", error_msg
);
7957 /* We specifically use it before defining it, so that gcc doesn't inline it,
7958 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7959 static void x_error_quitter (Display
*, XErrorEvent
*);
7961 /* This is the first-level handler for X protocol errors.
7962 It calls x_error_quitter or x_error_catcher. */
7965 x_error_handler (Display
*display
, XErrorEvent
*event
)
7968 if (event
->error_code
== BadMatch
7969 && event
->request_code
== X_SetInputFocus
7970 && event
->minor_code
== 0)
7976 if (x_error_message
)
7977 x_error_catcher (display
, event
);
7979 x_error_quitter (display
, event
);
7983 /* This is the usual handler for X protocol errors.
7984 It kills all frames on the display that we got the error for.
7985 If that was the only one, it prints an error message and kills Emacs. */
7987 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7989 /* On older GCC versions, just putting x_error_quitter
7990 after x_error_handler prevents inlining into the former. */
7992 static void NO_INLINE
7993 x_error_quitter (Display
*display
, XErrorEvent
*event
)
7995 char buf
[256], buf1
[356];
7997 /* Ignore BadName errors. They can happen because of fonts
7998 or colors that are not defined. */
8000 if (event
->error_code
== BadName
)
8003 /* Note that there is no real way portable across R3/R4 to get the
8004 original error handler. */
8006 XGetErrorText (display
, event
->error_code
, buf
, sizeof (buf
));
8007 sprintf (buf1
, "X protocol error: %s on protocol request %d",
8008 buf
, event
->request_code
);
8009 x_connection_closed (display
, buf1
);
8013 /* This is the handler for X IO errors, always.
8014 It kills all frames on the display that we lost touch with.
8015 If that was the only one, it prints an error message and kills Emacs. */
8018 x_io_error_quitter (Display
*display
)
8022 snprintf (buf
, sizeof buf
, "Connection lost to X server `%s'",
8023 DisplayString (display
));
8024 x_connection_closed (display
, buf
);
8028 /* Changing the font of the frame. */
8030 /* Give frame F the font FONT-OBJECT as its default font. The return
8031 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
8032 frame. If it is negative, generate a new fontset from
8036 x_new_font (struct frame
*f
, Lisp_Object font_object
, int fontset
)
8038 struct font
*font
= XFONT_OBJECT (font_object
);
8041 fontset
= fontset_from_font (font_object
);
8042 FRAME_FONTSET (f
) = fontset
;
8043 if (FRAME_FONT (f
) == font
)
8044 /* This font is already set in frame F. There's nothing more to
8048 FRAME_FONT (f
) = font
;
8049 FRAME_BASELINE_OFFSET (f
) = font
->baseline_offset
;
8050 FRAME_COLUMN_WIDTH (f
) = font
->average_width
;
8051 FRAME_SPACE_WIDTH (f
) = font
->space_width
;
8052 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (font
);
8054 compute_fringe_widths (f
, 1);
8056 /* Compute the scroll bar width in character columns. */
8057 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
8059 int wid
= FRAME_COLUMN_WIDTH (f
);
8060 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
8061 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
8065 int wid
= FRAME_COLUMN_WIDTH (f
);
8066 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
8069 if (FRAME_X_WINDOW (f
) != 0)
8071 /* Don't change the size of a tip frame; there's no point in
8072 doing it because it's done in Fx_show_tip, and it leads to
8073 problems because the tip frame has no widget. */
8074 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
8075 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
8080 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
8083 xic_set_xfontset (f
, SSDATA (fontset_ascii (fontset
)));
8092 /***********************************************************************
8094 ***********************************************************************/
8100 /* XIM destroy callback function, which is called whenever the
8101 connection to input method XIM dies. CLIENT_DATA contains a
8102 pointer to the x_display_info structure corresponding to XIM. */
8105 xim_destroy_callback (XIM xim
, XPointer client_data
, XPointer call_data
)
8107 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
8108 Lisp_Object frame
, tail
;
8112 /* No need to call XDestroyIC.. */
8113 FOR_EACH_FRAME (tail
, frame
)
8115 struct frame
*f
= XFRAME (frame
);
8116 if (FRAME_X_P (f
) && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
8118 FRAME_XIC (f
) = NULL
;
8119 xic_free_xfontset (f
);
8123 /* No need to call XCloseIM. */
8124 dpyinfo
->xim
= NULL
;
8125 XFree (dpyinfo
->xim_styles
);
8129 #endif /* HAVE_X11R6 */
8132 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8133 extern char *XSetIMValues (XIM
, ...);
8136 /* Open the connection to the XIM server on display DPYINFO.
8137 RESOURCE_NAME is the resource name Emacs uses. */
8140 xim_open_dpy (struct x_display_info
*dpyinfo
, char *resource_name
)
8148 XCloseIM (dpyinfo
->xim
);
8149 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
8156 XIMCallback destroy
;
8159 /* Get supported styles and XIM values. */
8160 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
8163 destroy
.callback
= xim_destroy_callback
;
8164 destroy
.client_data
= (XPointer
)dpyinfo
;
8165 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
8171 #endif /* HAVE_XIM */
8172 dpyinfo
->xim
= NULL
;
8176 #ifdef HAVE_X11R6_XIM
8178 /* XIM instantiate callback function, which is called whenever an XIM
8179 server is available. DISPLAY is the display of the XIM.
8180 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8181 when the callback was registered. */
8184 xim_instantiate_callback (Display
*display
, XPointer client_data
, XPointer call_data
)
8186 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
8187 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
8189 /* We don't support multiple XIM connections. */
8193 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
8195 /* Create XIC for the existing frames on the same display, as long
8196 as they have no XIC. */
8197 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
8199 Lisp_Object tail
, frame
;
8202 FOR_EACH_FRAME (tail
, frame
)
8204 struct frame
*f
= XFRAME (frame
);
8207 && FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
8208 if (FRAME_XIC (f
) == NULL
)
8210 create_frame_xic (f
);
8211 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
8212 xic_set_statusarea (f
);
8213 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
8215 struct window
*w
= XWINDOW (f
->selected_window
);
8216 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
8225 #endif /* HAVE_X11R6_XIM */
8228 /* Open a connection to the XIM server on display DPYINFO.
8229 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8230 connection only at the first time. On X11R6, open the connection
8231 in the XIM instantiate callback function. */
8234 xim_initialize (struct x_display_info
*dpyinfo
, char *resource_name
)
8236 dpyinfo
->xim
= NULL
;
8240 #ifdef HAVE_X11R6_XIM
8241 struct xim_inst_t
*xim_inst
;
8244 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
8245 dpyinfo
->xim_callback_data
= xim_inst
;
8246 xim_inst
->dpyinfo
= dpyinfo
;
8247 len
= strlen (resource_name
);
8248 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
8249 memcpy (xim_inst
->resource_name
, resource_name
, len
+ 1);
8250 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8251 resource_name
, emacs_class
,
8252 xim_instantiate_callback
,
8253 /* This is XPointer in XFree86
8254 but (XPointer *) on Tru64, at
8255 least, hence the configure test. */
8256 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8257 #else /* not HAVE_X11R6_XIM */
8258 xim_open_dpy (dpyinfo
, resource_name
);
8259 #endif /* not HAVE_X11R6_XIM */
8261 #endif /* HAVE_XIM */
8265 /* Close the connection to the XIM server on display DPYINFO. */
8268 xim_close_dpy (struct x_display_info
*dpyinfo
)
8273 #ifdef HAVE_X11R6_XIM
8274 if (dpyinfo
->display
)
8275 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
8277 xim_instantiate_callback
, NULL
);
8278 xfree (dpyinfo
->xim_callback_data
->resource_name
);
8279 xfree (dpyinfo
->xim_callback_data
);
8280 #endif /* HAVE_X11R6_XIM */
8281 if (dpyinfo
->display
)
8282 XCloseIM (dpyinfo
->xim
);
8283 dpyinfo
->xim
= NULL
;
8284 XFree (dpyinfo
->xim_styles
);
8286 #endif /* HAVE_XIM */
8289 #endif /* not HAVE_X11R6_XIM */
8293 /* Calculate the absolute position in frame F
8294 from its current recorded position values and gravity. */
8297 x_calc_absolute_position (struct frame
*f
)
8299 int flags
= f
->size_hint_flags
;
8301 /* We have nothing to do if the current position
8302 is already for the top-left corner. */
8303 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8306 /* Treat negative positions as relative to the leftmost bottommost
8307 position that fits on the screen. */
8308 if (flags
& XNegative
)
8309 f
->left_pos
= x_display_pixel_width (FRAME_X_DISPLAY_INFO (f
))
8310 - FRAME_PIXEL_WIDTH (f
) + f
->left_pos
;
8313 int height
= FRAME_PIXEL_HEIGHT (f
);
8315 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8316 /* Something is fishy here. When using Motif, starting Emacs with
8317 `-g -0-0', the frame appears too low by a few pixels.
8319 This seems to be so because initially, while Emacs is starting,
8320 the column widget's height and the frame's pixel height are
8321 different. The column widget's height is the right one. In
8322 later invocations, when Emacs is up, the frame's pixel height
8325 It's not obvious where the initial small difference comes from.
8326 2000-12-01, gerd. */
8328 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8331 if (flags
& YNegative
)
8332 f
->top_pos
= x_display_pixel_height (FRAME_X_DISPLAY_INFO (f
))
8333 - height
+ f
->top_pos
;
8336 /* The left_pos and top_pos
8337 are now relative to the top and left screen edges,
8338 so the flags should correspond. */
8339 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8342 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8343 to really change the position, and 0 when calling from
8344 x_make_frame_visible (in that case, XOFF and YOFF are the current
8345 position values). It is -1 when calling from x_set_frame_parameters,
8346 which means, do adjust for borders but don't change the gravity. */
8349 x_set_offset (struct frame
*f
, register int xoff
, register int yoff
, int change_gravity
)
8351 int modified_top
, modified_left
;
8353 if (change_gravity
> 0)
8355 FRAME_X_OUTPUT (f
)->left_before_move
= f
->left_pos
;
8356 FRAME_X_OUTPUT (f
)->top_before_move
= f
->top_pos
;
8360 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8362 f
->size_hint_flags
|= XNegative
;
8364 f
->size_hint_flags
|= YNegative
;
8365 f
->win_gravity
= NorthWestGravity
;
8367 x_calc_absolute_position (f
);
8370 x_wm_set_size_hint (f
, (long) 0, 0);
8372 modified_left
= f
->left_pos
;
8373 modified_top
= f
->top_pos
;
8375 if (change_gravity
!= 0 && FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8377 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8378 than the WM decorations. So we use the calculated offset instead
8379 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8380 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8381 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8384 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8385 modified_left
, modified_top
);
8387 x_sync_with_move (f
, f
->left_pos
, f
->top_pos
,
8388 FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8391 /* change_gravity is non-zero when this function is called from Lisp to
8392 programmatically move a frame. In that case, we call
8393 x_check_expected_move to discover if we have a "Type A" or "Type B"
8394 window manager, and, for a "Type A" window manager, adjust the position
8397 We call x_check_expected_move if a programmatic move occurred, and
8398 either the window manager type (A/B) is unknown or it is Type A but we
8399 need to compute the top/left offset adjustment for this frame. */
8401 if (change_gravity
!= 0 &&
8402 (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8403 || (FRAME_X_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
8404 && (FRAME_X_OUTPUT (f
)->move_offset_left
== 0
8405 && FRAME_X_OUTPUT (f
)->move_offset_top
== 0))))
8406 x_check_expected_move (f
, modified_left
, modified_top
);
8411 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8412 on the root window for frame F contains ATOMNAME.
8413 This is how a WM check shall be done according to the Window Manager
8414 Specification/Extended Window Manager Hints at
8415 http://freedesktop.org/wiki/Specifications/wm-spec. */
8418 wm_supports (struct frame
*f
, Atom want_atom
)
8421 unsigned long actual_size
, bytes_remaining
;
8422 int i
, rc
, actual_format
;
8423 Window wmcheck_window
;
8424 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8425 Window target_window
= dpyinfo
->root_window
;
8426 long max_len
= 65536;
8427 Display
*dpy
= FRAME_X_DISPLAY (f
);
8428 unsigned char *tmp_data
= NULL
;
8429 Atom target_type
= XA_WINDOW
;
8433 x_catch_errors (dpy
);
8434 rc
= XGetWindowProperty (dpy
, target_window
,
8435 dpyinfo
->Xatom_net_supporting_wm_check
,
8436 0, max_len
, False
, target_type
,
8437 &actual_type
, &actual_format
, &actual_size
,
8438 &bytes_remaining
, &tmp_data
);
8440 if (rc
!= Success
|| actual_type
!= XA_WINDOW
|| x_had_errors_p (dpy
))
8442 if (tmp_data
) XFree (tmp_data
);
8443 x_uncatch_errors ();
8448 wmcheck_window
= *(Window
*) tmp_data
;
8451 /* Check if window exists. */
8452 XSelectInput (dpy
, wmcheck_window
, StructureNotifyMask
);
8454 if (x_had_errors_p (dpy
))
8456 x_uncatch_errors ();
8461 if (dpyinfo
->net_supported_window
!= wmcheck_window
)
8463 /* Window changed, reload atoms */
8464 if (dpyinfo
->net_supported_atoms
!= NULL
)
8465 XFree (dpyinfo
->net_supported_atoms
);
8466 dpyinfo
->net_supported_atoms
= NULL
;
8467 dpyinfo
->nr_net_supported_atoms
= 0;
8468 dpyinfo
->net_supported_window
= 0;
8470 target_type
= XA_ATOM
;
8472 rc
= XGetWindowProperty (dpy
, target_window
,
8473 dpyinfo
->Xatom_net_supported
,
8474 0, max_len
, False
, target_type
,
8475 &actual_type
, &actual_format
, &actual_size
,
8476 &bytes_remaining
, &tmp_data
);
8478 if (rc
!= Success
|| actual_type
!= XA_ATOM
|| x_had_errors_p (dpy
))
8480 if (tmp_data
) XFree (tmp_data
);
8481 x_uncatch_errors ();
8486 dpyinfo
->net_supported_atoms
= (Atom
*)tmp_data
;
8487 dpyinfo
->nr_net_supported_atoms
= actual_size
;
8488 dpyinfo
->net_supported_window
= wmcheck_window
;
8493 for (i
= 0; rc
== 0 && i
< dpyinfo
->nr_net_supported_atoms
; ++i
)
8494 rc
= dpyinfo
->net_supported_atoms
[i
] == want_atom
;
8496 x_uncatch_errors ();
8503 set_wm_state (Lisp_Object frame
, int add
, Atom atom
, Atom value
)
8505 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (frame
));
8507 x_send_client_event (frame
, make_number (0), frame
,
8508 dpyinfo
->Xatom_net_wm_state
,
8510 /* 1 = add, 0 = remove */
8512 (make_number (add
? 1 : 0),
8514 (make_fixnum_or_float (atom
),
8516 ? Fcons (make_fixnum_or_float (value
), Qnil
)
8521 x_set_sticky (struct frame
*f
, Lisp_Object new_value
, Lisp_Object old_value
)
8524 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8526 XSETFRAME (frame
, f
);
8528 set_wm_state (frame
, NILP (new_value
) ? 0 : 1,
8529 dpyinfo
->Xatom_net_wm_state_sticky
, None
);
8532 /* Return the current _NET_WM_STATE.
8533 SIZE_STATE is set to one of the FULLSCREEN_* values.
8534 STICKY is set to 1 if the sticky state is set, 0 if not.
8536 Return non-zero if we are not hidden, zero if we are. */
8539 get_current_wm_state (struct frame
*f
,
8545 unsigned long actual_size
, bytes_remaining
;
8546 int i
, rc
, actual_format
, is_hidden
= 0;
8547 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8548 long max_len
= 65536;
8549 Display
*dpy
= FRAME_X_DISPLAY (f
);
8550 unsigned char *tmp_data
= NULL
;
8551 Atom target_type
= XA_ATOM
;
8554 *size_state
= FULLSCREEN_NONE
;
8557 x_catch_errors (dpy
);
8558 rc
= XGetWindowProperty (dpy
, window
, dpyinfo
->Xatom_net_wm_state
,
8559 0, max_len
, False
, target_type
,
8560 &actual_type
, &actual_format
, &actual_size
,
8561 &bytes_remaining
, &tmp_data
);
8563 if (rc
!= Success
|| actual_type
!= target_type
|| x_had_errors_p (dpy
))
8565 if (tmp_data
) XFree (tmp_data
);
8566 x_uncatch_errors ();
8568 return ! f
->iconified
;
8571 x_uncatch_errors ();
8573 for (i
= 0; i
< actual_size
; ++i
)
8575 Atom a
= ((Atom
*)tmp_data
)[i
];
8576 if (a
== dpyinfo
->Xatom_net_wm_state_hidden
)
8579 f
->output_data
.x
->net_wm_state_hidden_seen
= 1;
8581 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_horz
)
8583 if (*size_state
== FULLSCREEN_HEIGHT
)
8584 *size_state
= FULLSCREEN_MAXIMIZED
;
8586 *size_state
= FULLSCREEN_WIDTH
;
8588 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_vert
)
8590 if (*size_state
== FULLSCREEN_WIDTH
)
8591 *size_state
= FULLSCREEN_MAXIMIZED
;
8593 *size_state
= FULLSCREEN_HEIGHT
;
8595 else if (a
== dpyinfo
->Xatom_net_wm_state_fullscreen
)
8596 *size_state
= FULLSCREEN_BOTH
;
8597 else if (a
== dpyinfo
->Xatom_net_wm_state_sticky
)
8601 if (tmp_data
) XFree (tmp_data
);
8606 /* Do fullscreen as specified in extended window manager hints */
8609 do_ewmh_fullscreen (struct frame
*f
)
8611 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8612 int have_net_atom
= wm_supports (f
, dpyinfo
->Xatom_net_wm_state
);
8615 (void)get_current_wm_state (f
, FRAME_OUTER_WINDOW (f
), &cur
, &dummy
);
8617 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8618 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8620 have_net_atom
= wm_supports (f
, dpyinfo
->Xatom_net_wm_state_fullscreen
);
8622 if (have_net_atom
&& cur
!= f
->want_fullscreen
)
8626 XSETFRAME (frame
, f
);
8628 /* Keep number of calls to set_wm_state as low as possible.
8629 Some window managers, or possible Gtk+, hangs when too many
8630 are sent at once. */
8631 switch (f
->want_fullscreen
)
8633 case FULLSCREEN_BOTH
:
8634 if (cur
== FULLSCREEN_WIDTH
|| cur
== FULLSCREEN_MAXIMIZED
8635 || cur
== FULLSCREEN_HEIGHT
)
8636 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8637 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8638 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8640 case FULLSCREEN_WIDTH
:
8641 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_HEIGHT
8642 || cur
== FULLSCREEN_MAXIMIZED
)
8643 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
,
8644 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8645 if (cur
!= FULLSCREEN_MAXIMIZED
)
8646 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
8648 case FULLSCREEN_HEIGHT
:
8649 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_WIDTH
8650 || cur
== FULLSCREEN_MAXIMIZED
)
8651 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
,
8652 dpyinfo
->Xatom_net_wm_state_maximized_horz
);
8653 if (cur
!= FULLSCREEN_MAXIMIZED
)
8654 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_vert
, None
);
8656 case FULLSCREEN_MAXIMIZED
:
8657 if (cur
== FULLSCREEN_BOTH
)
8658 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8659 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8660 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8662 case FULLSCREEN_NONE
:
8663 if (cur
== FULLSCREEN_BOTH
)
8664 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8666 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8667 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8670 f
->want_fullscreen
= FULLSCREEN_NONE
;
8674 return have_net_atom
;
8678 XTfullscreen_hook (FRAME_PTR f
)
8680 if (f
->async_visible
)
8683 x_check_fullscreen (f
);
8691 x_handle_net_wm_state (struct frame
*f
, XPropertyEvent
*event
)
8693 int value
= FULLSCREEN_NONE
;
8696 int not_hidden
= get_current_wm_state (f
, event
->window
, &value
, &sticky
);
8701 case FULLSCREEN_WIDTH
:
8704 case FULLSCREEN_HEIGHT
:
8707 case FULLSCREEN_BOTH
:
8710 case FULLSCREEN_MAXIMIZED
:
8715 store_frame_param (f
, Qfullscreen
, lval
);
8716 store_frame_param (f
, Qsticky
, sticky
? Qt
: Qnil
);
8721 /* Check if we need to resize the frame due to a fullscreen request.
8722 If so needed, resize the frame. */
8724 x_check_fullscreen (struct frame
*f
)
8726 if (do_ewmh_fullscreen (f
))
8729 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
8730 return; /* Only fullscreen without WM or with EWM hints (above). */
8732 /* Setting fullscreen to nil doesn't do anything. We could save the
8733 last non-fullscreen size and restore it, but it seems like a
8734 lot of work for this unusual case (no window manager running). */
8736 if (f
->want_fullscreen
!= FULLSCREEN_NONE
)
8738 int width
= FRAME_PIXEL_WIDTH (f
), height
= FRAME_PIXEL_HEIGHT (f
);
8739 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
8741 switch (f
->want_fullscreen
)
8743 /* No difference between these two when there is no WM */
8744 case FULLSCREEN_BOTH
:
8745 case FULLSCREEN_MAXIMIZED
:
8746 width
= x_display_pixel_width (dpyinfo
);
8747 height
= x_display_pixel_height (dpyinfo
);
8749 case FULLSCREEN_WIDTH
:
8750 width
= x_display_pixel_width (dpyinfo
);
8752 case FULLSCREEN_HEIGHT
:
8753 height
= x_display_pixel_height (dpyinfo
);
8756 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8761 /* This function is called by x_set_offset to determine whether the window
8762 manager interfered with the positioning of the frame. Type A window
8763 managers position the surrounding window manager decorations a small
8764 amount above and left of the user-supplied position. Type B window
8765 managers position the surrounding window manager decorations at the
8766 user-specified position. If we detect a Type A window manager, we
8767 compensate by moving the window right and down by the proper amount. */
8770 x_check_expected_move (struct frame
*f
, int expected_left
, int expected_top
)
8772 int current_left
= 0, current_top
= 0;
8774 /* x_real_positions returns the left and top offsets of the outermost
8775 window manager window around the frame. */
8777 x_real_positions (f
, ¤t_left
, ¤t_top
);
8779 if (current_left
!= expected_left
|| current_top
!= expected_top
)
8781 /* It's a "Type A" window manager. */
8786 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8787 FRAME_X_OUTPUT (f
)->move_offset_left
= expected_left
- current_left
;
8788 FRAME_X_OUTPUT (f
)->move_offset_top
= expected_top
- current_top
;
8790 /* Now fix the mispositioned frame's location. */
8792 adjusted_left
= expected_left
+ FRAME_X_OUTPUT (f
)->move_offset_left
;
8793 adjusted_top
= expected_top
+ FRAME_X_OUTPUT (f
)->move_offset_top
;
8795 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8796 adjusted_left
, adjusted_top
);
8798 x_sync_with_move (f
, expected_left
, expected_top
, 0);
8801 /* It's a "Type B" window manager. We don't have to adjust the
8802 frame's position. */
8804 FRAME_X_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8808 /* Wait for XGetGeometry to return up-to-date position information for a
8809 recently-moved frame. Call this immediately after calling XMoveWindow.
8810 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8811 frame has been moved to, so we use a fuzzy position comparison instead
8812 of an exact comparison. */
8815 x_sync_with_move (struct frame
*f
, int left
, int top
, int fuzzy
)
8819 while (count
++ < 50)
8821 int current_left
= 0, current_top
= 0;
8823 /* In theory, this call to XSync only needs to happen once, but in
8824 practice, it doesn't seem to work, hence the need for the surrounding
8827 XSync (FRAME_X_DISPLAY (f
), False
);
8828 x_real_positions (f
, ¤t_left
, ¤t_top
);
8832 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8835 if (eabs (current_left
- left
) <= 10
8836 && eabs (current_top
- top
) <= 40)
8839 else if (current_left
== left
&& current_top
== top
)
8843 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8844 will then return up-to-date position info. */
8846 wait_reading_process_output (0, 500000, 0, 0, Qnil
, NULL
, 0);
8850 /* Wait for an event on frame F matching EVENTTYPE. */
8852 x_wait_for_event (struct frame
*f
, int eventtype
)
8854 int level
= interrupt_input_blocked
;
8857 EMACS_TIME tmo
, tmo_at
, time_now
;
8858 int fd
= ConnectionNumber (FRAME_X_DISPLAY (f
));
8860 pending_event_wait
.f
= f
;
8861 pending_event_wait
.eventtype
= eventtype
;
8863 /* Set timeout to 0.1 second. Hopefully not noticeable.
8864 Maybe it should be configurable. */
8865 EMACS_SET_SECS_USECS (tmo
, 0, 100000);
8866 EMACS_GET_TIME (tmo_at
);
8867 EMACS_ADD_TIME (tmo_at
, tmo_at
, tmo
);
8869 while (pending_event_wait
.eventtype
)
8871 interrupt_input_pending
= 1;
8872 TOTALLY_UNBLOCK_INPUT
;
8873 /* XTread_socket is called after unblock. */
8875 interrupt_input_blocked
= level
;
8880 EMACS_GET_TIME (time_now
);
8881 EMACS_SUB_TIME (tmo
, tmo_at
, time_now
);
8883 if (EMACS_TIME_NEG_P (tmo
) || select (fd
+1, &fds
, NULL
, NULL
, &tmo
) == 0)
8884 break; /* Timeout */
8886 pending_event_wait
.f
= 0;
8887 pending_event_wait
.eventtype
= 0;
8891 /* Change the size of frame F's X window to COLS/ROWS in the case F
8892 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8893 top-left-corner window gravity for this size change and subsequent
8894 size changes. Otherwise we leave the window gravity unchanged. */
8897 x_set_window_size_1 (struct frame
*f
, int change_gravity
, int cols
, int rows
)
8899 int pixelwidth
, pixelheight
;
8901 check_frame_size (f
, &rows
, &cols
);
8902 f
->scroll_bar_actual_width
8903 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
8905 : FRAME_CONFIG_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
));
8907 compute_fringe_widths (f
, 0);
8909 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
)
8910 + FRAME_TOOLBAR_WIDTH (f
);
8911 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
)
8912 + FRAME_MENUBAR_HEIGHT (f
) + FRAME_TOOLBAR_HEIGHT (f
);
8914 if (change_gravity
) f
->win_gravity
= NorthWestGravity
;
8915 x_wm_set_size_hint (f
, (long) 0, 0);
8916 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8917 pixelwidth
, pixelheight
);
8920 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8921 receive in the ConfigureNotify event; if we get what we asked
8922 for, then the event won't cause the screen to become garbaged, so
8923 we have to make sure to do it here. */
8924 SET_FRAME_GARBAGED (f
);
8926 /* Now, strictly speaking, we can't be sure that this is accurate,
8927 but the window manager will get around to dealing with the size
8928 change request eventually, and we'll hear how it went when the
8929 ConfigureNotify event gets here.
8931 We could just not bother storing any of this information here,
8932 and let the ConfigureNotify event set everything up, but that
8933 might be kind of confusing to the Lisp code, since size changes
8934 wouldn't be reported in the frame parameters until some random
8935 point in the future when the ConfigureNotify event arrives.
8937 We pass 1 for DELAY since we can't run Lisp code inside of
8940 /* But the ConfigureNotify may in fact never arrive, and then this is
8941 not right if the frame is visible. Instead wait (with timeout)
8942 for the ConfigureNotify. */
8943 if (f
->async_visible
)
8944 x_wait_for_event (f
, ConfigureNotify
);
8947 change_frame_size (f
, rows
, cols
, 0, 1, 0);
8948 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
8949 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
8955 /* Call this to change the size of frame F's x-window.
8956 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8957 for this size change and subsequent size changes.
8958 Otherwise we leave the window gravity unchanged. */
8961 x_set_window_size (struct frame
*f
, int change_gravity
, int cols
, int rows
)
8965 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
8969 /* When the frame is maximized/fullscreen or running under for
8970 example Xmonad, x_set_window_size_1 will be a no-op.
8971 In that case, the right thing to do is extend rows/cols to
8972 the current frame size. We do that first if x_set_window_size_1
8973 turns out to not be a no-op (there is no way to know).
8974 The size will be adjusted again if the frame gets a
8975 ConfigureNotify event as a result of x_set_window_size. */
8976 int pixelh
= FRAME_PIXEL_HEIGHT (f
);
8977 #ifdef USE_X_TOOLKIT
8978 /* The menu bar is not part of text lines. The tool bar
8980 pixelh
-= FRAME_MENUBAR_HEIGHT (f
);
8982 r
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelh
);
8983 /* Update f->scroll_bar_actual_width because it is used in
8984 FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
8985 f
->scroll_bar_actual_width
8986 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
8987 c
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, FRAME_PIXEL_WIDTH (f
));
8988 change_frame_size (f
, r
, c
, 0, 1, 0);
8992 if (FRAME_GTK_WIDGET (f
))
8993 xg_frame_set_char_size (f
, cols
, rows
);
8995 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
8996 #else /* not USE_GTK */
8998 x_set_window_size_1 (f
, change_gravity
, cols
, rows
);
9000 #endif /* not USE_GTK */
9002 /* If cursor was outside the new size, mark it as off. */
9003 mark_window_cursors_off (XWINDOW (f
->root_window
));
9005 /* Clear out any recollection of where the mouse highlighting was,
9006 since it might be in a place that's outside the new frame size.
9007 Actually checking whether it is outside is a pain in the neck,
9008 so don't try--just let the highlighting be done afresh with new size. */
9009 cancel_mouse_face (f
);
9014 /* Mouse warping. */
9017 x_set_mouse_position (struct frame
*f
, int x
, int y
)
9021 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
9022 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
9024 if (pix_x
< 0) pix_x
= 0;
9025 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
9027 if (pix_y
< 0) pix_y
= 0;
9028 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
9032 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
9033 0, 0, 0, 0, pix_x
, pix_y
);
9037 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
9040 x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
)
9044 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
9045 0, 0, 0, 0, pix_x
, pix_y
);
9049 /* Raise frame F. */
9052 x_raise_frame (struct frame
*f
)
9055 if (f
->async_visible
)
9056 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
9058 XFlush (FRAME_X_DISPLAY (f
));
9062 /* Lower frame F. */
9065 x_lower_frame (struct frame
*f
)
9067 if (f
->async_visible
)
9070 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
9071 XFlush (FRAME_X_DISPLAY (f
));
9076 /* Request focus with XEmbed */
9079 xembed_request_focus (FRAME_PTR f
)
9081 /* See XEmbed Protocol Specification at
9082 http://freedesktop.org/wiki/Specifications/xembed-spec */
9083 if (f
->async_visible
)
9084 xembed_send_message (f
, CurrentTime
,
9085 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
9088 /* Activate frame with Extended Window Manager Hints */
9091 x_ewmh_activate_frame (FRAME_PTR f
)
9093 /* See Window Manager Specification/Extended Window Manager Hints at
9094 http://freedesktop.org/wiki/Specifications/wm-spec */
9096 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9097 if (f
->async_visible
&& wm_supports (f
, dpyinfo
->Xatom_net_active_window
))
9100 XSETFRAME (frame
, f
);
9101 x_send_client_event (frame
, make_number (0), frame
,
9102 dpyinfo
->Xatom_net_active_window
,
9104 Fcons (make_number (1),
9105 Fcons (make_number (last_user_time
),
9111 XTframe_raise_lower (FRAME_PTR f
, int raise_flag
)
9119 /* XEmbed implementation. */
9121 #if defined USE_X_TOOLKIT || ! defined USE_GTK
9123 /* XEmbed implementation. */
9125 #define XEMBED_VERSION 0
9128 xembed_set_info (struct frame
*f
, enum xembed_info flags
)
9130 unsigned long data
[2];
9131 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9133 data
[0] = XEMBED_VERSION
;
9136 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9137 dpyinfo
->Xatom_XEMBED_INFO
, dpyinfo
->Xatom_XEMBED_INFO
,
9138 32, PropModeReplace
, (unsigned char *) data
, 2);
9140 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
9143 xembed_send_message (struct frame
*f
, Time t
, enum xembed_message msg
,
9144 long int detail
, long int data1
, long int data2
)
9148 event
.xclient
.type
= ClientMessage
;
9149 event
.xclient
.window
= FRAME_X_OUTPUT (f
)->parent_desc
;
9150 event
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_XEMBED
;
9151 event
.xclient
.format
= 32;
9152 event
.xclient
.data
.l
[0] = t
;
9153 event
.xclient
.data
.l
[1] = msg
;
9154 event
.xclient
.data
.l
[2] = detail
;
9155 event
.xclient
.data
.l
[3] = data1
;
9156 event
.xclient
.data
.l
[4] = data2
;
9158 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_OUTPUT (f
)->parent_desc
,
9159 False
, NoEventMask
, &event
);
9160 XSync (FRAME_X_DISPLAY (f
), False
);
9163 /* Change of visibility. */
9165 /* This tries to wait until the frame is really visible.
9166 However, if the window manager asks the user where to position
9167 the frame, this will return before the user finishes doing that.
9168 The frame will not actually be visible at that time,
9169 but it will become visible later when the window manager
9170 finishes with it. */
9173 x_make_frame_visible (struct frame
*f
)
9176 int original_top
, original_left
;
9177 int retry_count
= 2;
9183 type
= x_icon_type (f
);
9185 x_bitmap_icon (f
, type
);
9187 if (! FRAME_VISIBLE_P (f
))
9189 /* We test FRAME_GARBAGED_P here to make sure we don't
9190 call x_set_offset a second time
9191 if we get to x_make_frame_visible a second time
9192 before the window gets really visible. */
9193 if (! FRAME_ICONIFIED_P (f
)
9194 && ! FRAME_X_EMBEDDED_P (f
)
9195 && ! f
->output_data
.x
->asked_for_visible
)
9196 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9198 f
->output_data
.x
->asked_for_visible
= 1;
9200 if (! EQ (Vx_no_window_manager
, Qt
))
9201 x_wm_set_window_state (f
, NormalState
);
9202 #ifdef USE_X_TOOLKIT
9203 if (FRAME_X_EMBEDDED_P (f
))
9204 xembed_set_info (f
, XEMBED_MAPPED
);
9207 /* This was XtPopup, but that did nothing for an iconified frame. */
9208 XtMapWidget (f
->output_data
.x
->widget
);
9210 #else /* not USE_X_TOOLKIT */
9212 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
9213 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
9215 if (FRAME_X_EMBEDDED_P (f
))
9216 xembed_set_info (f
, XEMBED_MAPPED
);
9218 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9219 #endif /* not USE_GTK */
9220 #endif /* not USE_X_TOOLKIT */
9223 XFlush (FRAME_X_DISPLAY (f
));
9225 /* Synchronize to ensure Emacs knows the frame is visible
9226 before we do anything else. We do this loop with input not blocked
9227 so that incoming events are handled. */
9231 /* This must be before UNBLOCK_INPUT
9232 since events that arrive in response to the actions above
9233 will set it when they are handled. */
9234 int previously_visible
= f
->output_data
.x
->has_been_visible
;
9236 original_left
= f
->left_pos
;
9237 original_top
= f
->top_pos
;
9239 /* This must come after we set COUNT. */
9242 /* We unblock here so that arriving X events are processed. */
9244 /* Now move the window back to where it was "supposed to be".
9245 But don't do it if the gravity is negative.
9246 When the gravity is negative, this uses a position
9247 that is 3 pixels too low. Perhaps that's really the border width.
9249 Don't do this if the window has never been visible before,
9250 because the window manager may choose the position
9251 and we don't want to override it. */
9253 if (! FRAME_VISIBLE_P (f
)
9254 && ! FRAME_ICONIFIED_P (f
)
9255 && ! FRAME_X_EMBEDDED_P (f
)
9256 && f
->win_gravity
== NorthWestGravity
9257 && previously_visible
)
9261 unsigned int width
, height
, border
, depth
;
9265 /* On some window managers (such as FVWM) moving an existing
9266 window, even to the same place, causes the window manager
9267 to introduce an offset. This can cause the window to move
9268 to an unexpected location. Check the geometry (a little
9269 slow here) and then verify that the window is in the right
9270 place. If the window is not in the right place, move it
9271 there, and take the potential window manager hit. */
9272 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9273 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
9275 if (original_left
!= x
|| original_top
!= y
)
9276 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
9277 original_left
, original_top
);
9282 XSETFRAME (frame
, f
);
9284 /* Wait until the frame is visible. Process X events until a
9285 MapNotify event has been seen, or until we think we won't get a
9286 MapNotify at all.. */
9287 for (count
= input_signal_count
+ 10;
9288 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
9290 /* Force processing of queued events. */
9293 /* Machines that do polling rather than SIGIO have been
9294 observed to go into a busy-wait here. So we'll fake an
9295 alarm signal to let the handler know that there's something
9296 to be read. We used to raise a real alarm, but it seems
9297 that the handler isn't always enabled here. This is
9299 if (input_polling_used ())
9301 /* It could be confusing if a real alarm arrives while
9302 processing the fake one. Turn it off and let the
9303 handler reset it. */
9304 int old_poll_suppress_count
= poll_suppress_count
;
9305 poll_suppress_count
= 1;
9306 poll_for_input_1 ();
9307 poll_suppress_count
= old_poll_suppress_count
;
9310 /* See if a MapNotify event has been processed. */
9311 FRAME_SAMPLE_VISIBILITY (f
);
9316 (let ((f (selected-frame)))
9320 the frame is not raised with various window managers on
9321 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9322 unknown reason, the call to XtMapWidget is completely ignored.
9323 Mapping the widget a second time works. */
9325 if (!FRAME_VISIBLE_P (f
) && --retry_count
!= 0)
9330 /* Change from mapped state to withdrawn state. */
9332 /* Make the frame visible (mapped and not iconified). */
9335 x_make_frame_invisible (struct frame
*f
)
9339 /* Use the frame's outermost window, not the one we normally draw on. */
9340 window
= FRAME_OUTER_WINDOW (f
);
9342 /* Don't keep the highlight on an invisible frame. */
9343 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9344 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9348 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9349 that the current position of the window is user-specified, rather than
9350 program-specified, so that when the window is mapped again, it will be
9351 placed at the same location, without forcing the user to position it
9352 by hand again (they have already done that once for this window.) */
9353 x_wm_set_size_hint (f
, (long) 0, 1);
9356 if (FRAME_GTK_OUTER_WIDGET (f
))
9357 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
9360 if (FRAME_X_EMBEDDED_P (f
))
9361 xembed_set_info (f
, 0);
9366 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
9367 DefaultScreen (FRAME_X_DISPLAY (f
))))
9369 UNBLOCK_INPUT_RESIGNAL
;
9370 error ("Can't notify window manager of window withdrawal");
9374 /* We can't distinguish this from iconification
9375 just by the event that we get from the server.
9376 So we can't win using the usual strategy of letting
9377 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9378 and synchronize with the server to make sure we agree. */
9380 FRAME_ICONIFIED_P (f
) = 0;
9381 f
->async_visible
= 0;
9382 f
->async_iconified
= 0;
9389 /* Change window state from mapped to iconified. */
9392 x_iconify_frame (struct frame
*f
)
9394 #ifdef USE_X_TOOLKIT
9399 /* Don't keep the highlight on an invisible frame. */
9400 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9401 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9403 if (f
->async_iconified
)
9408 FRAME_SAMPLE_VISIBILITY (f
);
9410 type
= x_icon_type (f
);
9412 x_bitmap_icon (f
, type
);
9414 #if defined (USE_GTK)
9415 if (FRAME_GTK_OUTER_WIDGET (f
))
9417 if (! FRAME_VISIBLE_P (f
))
9418 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
9420 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
9423 f
->async_iconified
= 1;
9424 f
->async_visible
= 0;
9430 #ifdef USE_X_TOOLKIT
9432 if (! FRAME_VISIBLE_P (f
))
9434 if (! EQ (Vx_no_window_manager
, Qt
))
9435 x_wm_set_window_state (f
, IconicState
);
9436 /* This was XtPopup, but that did nothing for an iconified frame. */
9437 XtMapWidget (f
->output_data
.x
->widget
);
9438 /* The server won't give us any event to indicate
9439 that an invisible frame was changed to an icon,
9440 so we have to record it here. */
9443 f
->async_iconified
= 1;
9444 f
->async_visible
= 0;
9449 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
9450 XtWindow (f
->output_data
.x
->widget
),
9451 DefaultScreen (FRAME_X_DISPLAY (f
)));
9455 error ("Can't notify window manager of iconification");
9457 f
->async_iconified
= 1;
9458 f
->async_visible
= 0;
9462 XFlush (FRAME_X_DISPLAY (f
));
9464 #else /* not USE_X_TOOLKIT */
9466 /* Make sure the X server knows where the window should be positioned,
9467 in case the user deiconifies with the window manager. */
9468 if (! FRAME_VISIBLE_P (f
)
9469 && ! FRAME_ICONIFIED_P (f
)
9470 && ! FRAME_X_EMBEDDED_P (f
))
9471 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9473 /* Since we don't know which revision of X we're running, we'll use both
9474 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9476 /* X11R4: send a ClientMessage to the window manager using the
9477 WM_CHANGE_STATE type. */
9481 msg
.xclient
.window
= FRAME_X_WINDOW (f
);
9482 msg
.xclient
.type
= ClientMessage
;
9483 msg
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
9484 msg
.xclient
.format
= 32;
9485 msg
.xclient
.data
.l
[0] = IconicState
;
9487 if (! XSendEvent (FRAME_X_DISPLAY (f
),
9488 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
9490 SubstructureRedirectMask
| SubstructureNotifyMask
,
9493 UNBLOCK_INPUT_RESIGNAL
;
9494 error ("Can't notify window manager of iconification");
9498 /* X11R3: set the initial_state field of the window manager hints to
9500 x_wm_set_window_state (f
, IconicState
);
9502 if (!FRAME_VISIBLE_P (f
))
9504 /* If the frame was withdrawn, before, we must map it. */
9505 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9508 f
->async_iconified
= 1;
9509 f
->async_visible
= 0;
9511 XFlush (FRAME_X_DISPLAY (f
));
9513 #endif /* not USE_X_TOOLKIT */
9517 /* Free X resources of frame F. */
9520 x_free_frame_resources (struct frame
*f
)
9522 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9523 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
9524 #ifdef USE_X_TOOLKIT
9526 struct scroll_bar
*b
;
9531 /* If a display connection is dead, don't try sending more
9532 commands to the X server. */
9533 if (dpyinfo
->display
)
9535 /* We must free faces before destroying windows because some
9536 font-driver (e.g. xft) access a window while finishing a
9538 if (FRAME_FACE_CACHE (f
))
9539 free_frame_faces (f
);
9541 if (f
->output_data
.x
->icon_desc
)
9542 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
9544 #ifdef USE_X_TOOLKIT
9545 /* Explicitly destroy the scroll bars of the frame. Without
9546 this, we get "BadDrawable" errors from the toolkit later on,
9547 presumably from expose events generated for the disappearing
9548 toolkit scroll bars. */
9549 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
9551 b
= XSCROLL_BAR (bar
);
9552 x_scroll_bar_remove (b
);
9561 #ifdef USE_X_TOOLKIT
9562 if (f
->output_data
.x
->widget
)
9564 XtDestroyWidget (f
->output_data
.x
->widget
);
9565 f
->output_data
.x
->widget
= NULL
;
9567 /* Tooltips don't have widgets, only a simple X window, even if
9568 we are using a toolkit. */
9569 else if (FRAME_X_WINDOW (f
))
9570 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9572 free_frame_menubar (f
);
9573 #else /* !USE_X_TOOLKIT */
9576 xg_free_frame_widgets (f
);
9577 #endif /* USE_GTK */
9579 if (FRAME_X_WINDOW (f
))
9580 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9581 #endif /* !USE_X_TOOLKIT */
9583 unload_color (f
, FRAME_FOREGROUND_PIXEL (f
));
9584 unload_color (f
, FRAME_BACKGROUND_PIXEL (f
));
9585 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9586 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9587 unload_color (f
, f
->output_data
.x
->border_pixel
);
9588 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9590 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9591 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9592 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9593 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9594 #ifdef USE_TOOLKIT_SCROLL_BARS
9595 /* Scrollbar shadow colors. */
9596 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9597 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9598 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9599 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9600 #endif /* USE_TOOLKIT_SCROLL_BARS */
9601 if (f
->output_data
.x
->white_relief
.allocated_p
)
9602 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9603 if (f
->output_data
.x
->black_relief
.allocated_p
)
9604 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9607 XFlush (FRAME_X_DISPLAY (f
));
9610 xfree (f
->output_data
.x
->saved_menu_event
);
9611 xfree (f
->output_data
.x
);
9612 f
->output_data
.x
= NULL
;
9614 if (f
== dpyinfo
->x_focus_frame
)
9615 dpyinfo
->x_focus_frame
= 0;
9616 if (f
== dpyinfo
->x_focus_event_frame
)
9617 dpyinfo
->x_focus_event_frame
= 0;
9618 if (f
== dpyinfo
->x_highlight_frame
)
9619 dpyinfo
->x_highlight_frame
= 0;
9621 if (f
== hlinfo
->mouse_face_mouse_frame
)
9623 hlinfo
->mouse_face_beg_row
9624 = hlinfo
->mouse_face_beg_col
= -1;
9625 hlinfo
->mouse_face_end_row
9626 = hlinfo
->mouse_face_end_col
= -1;
9627 hlinfo
->mouse_face_window
= Qnil
;
9628 hlinfo
->mouse_face_deferred_gc
= 0;
9629 hlinfo
->mouse_face_mouse_frame
= 0;
9636 /* Destroy the X window of frame F. */
9639 x_destroy_window (struct frame
*f
)
9641 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9643 /* If a display connection is dead, don't try sending more
9644 commands to the X server. */
9645 if (dpyinfo
->display
!= 0)
9646 x_free_frame_resources (f
);
9648 dpyinfo
->reference_count
--;
9652 /* Setting window manager hints. */
9654 /* Set the normal size hints for the window manager, for frame F.
9655 FLAGS is the flags word to use--or 0 meaning preserve the flags
9656 that the window now has.
9657 If USER_POSITION is nonzero, we set the USPosition
9658 flag (this is useful when FLAGS is 0).
9659 The GTK version is in gtkutils.c */
9663 x_wm_set_size_hint (struct frame
*f
, long flags
, int user_position
)
9665 XSizeHints size_hints
;
9666 Window window
= FRAME_OUTER_WINDOW (f
);
9668 #ifdef USE_X_TOOLKIT
9669 if (f
->output_data
.x
->widget
)
9671 widget_update_wm_size_hints (f
->output_data
.x
->widget
);
9676 /* Setting PMaxSize caused various problems. */
9677 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9679 size_hints
.x
= f
->left_pos
;
9680 size_hints
.y
= f
->top_pos
;
9682 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9683 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9685 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
9686 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
9687 size_hints
.max_width
= x_display_pixel_width (FRAME_X_DISPLAY_INFO (f
))
9688 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9689 size_hints
.max_height
= x_display_pixel_height (FRAME_X_DISPLAY_INFO (f
))
9690 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9692 /* Calculate the base and minimum sizes. */
9694 int base_width
, base_height
;
9695 int min_rows
= 0, min_cols
= 0;
9697 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9698 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9700 check_frame_size (f
, &min_rows
, &min_cols
);
9702 /* The window manager uses the base width hints to calculate the
9703 current number of rows and columns in the frame while
9704 resizing; min_width and min_height aren't useful for this
9705 purpose, since they might not give the dimensions for a
9706 zero-row, zero-column frame.
9708 We use the base_width and base_height members if we have
9709 them; otherwise, we set the min_width and min_height members
9710 to the size for a zero x zero frame. */
9712 size_hints
.flags
|= PBaseSize
;
9713 size_hints
.base_width
= base_width
;
9714 size_hints
.base_height
= base_height
+ FRAME_MENUBAR_HEIGHT (f
);
9715 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
9716 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
9719 /* If we don't need the old flags, we don't need the old hint at all. */
9722 size_hints
.flags
|= flags
;
9727 XSizeHints hints
; /* Sometimes I hate X Windows... */
9728 long supplied_return
;
9731 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9735 size_hints
.flags
|= flags
;
9740 if (hints
.flags
& PSize
)
9741 size_hints
.flags
|= PSize
;
9742 if (hints
.flags
& PPosition
)
9743 size_hints
.flags
|= PPosition
;
9744 if (hints
.flags
& USPosition
)
9745 size_hints
.flags
|= USPosition
;
9746 if (hints
.flags
& USSize
)
9747 size_hints
.flags
|= USSize
;
9754 size_hints
.win_gravity
= f
->win_gravity
;
9755 size_hints
.flags
|= PWinGravity
;
9759 size_hints
.flags
&= ~ PPosition
;
9760 size_hints
.flags
|= USPosition
;
9762 #endif /* PWinGravity */
9764 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9766 #endif /* not USE_GTK */
9768 /* Used for IconicState or NormalState */
9771 x_wm_set_window_state (struct frame
*f
, int state
)
9773 #ifdef USE_X_TOOLKIT
9776 XtSetArg (al
[0], XtNinitialState
, state
);
9777 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9778 #else /* not USE_X_TOOLKIT */
9779 Window window
= FRAME_X_WINDOW (f
);
9781 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9782 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9784 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9785 #endif /* not USE_X_TOOLKIT */
9789 x_wm_set_icon_pixmap (struct frame
*f
, ptrdiff_t pixmap_id
)
9791 Pixmap icon_pixmap
, icon_mask
;
9793 #if !defined USE_X_TOOLKIT && !defined USE_GTK
9794 Window window
= FRAME_OUTER_WINDOW (f
);
9799 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9800 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9801 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9802 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9806 /* It seems there is no way to turn off use of an icon
9814 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
);
9818 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9822 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9823 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9824 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9825 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9828 #else /* not USE_X_TOOLKIT && not USE_GTK */
9830 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9831 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9833 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9837 x_wm_set_icon_position (struct frame
*f
, int icon_x
, int icon_y
)
9839 Window window
= FRAME_OUTER_WINDOW (f
);
9841 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9842 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9843 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9845 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9849 /***********************************************************************
9851 ***********************************************************************/
9855 /* Check that FONT is valid on frame F. It is if it can be found in F's
9859 x_check_font (struct frame
*f
, struct font
*font
)
9861 xassert (font
!= NULL
&& ! NILP (font
->props
[FONT_TYPE_INDEX
]));
9862 if (font
->driver
->check
)
9863 xassert (font
->driver
->check (f
, font
) == 0);
9866 #endif /* GLYPH_DEBUG != 0 */
9869 /***********************************************************************
9871 ***********************************************************************/
9873 #ifdef USE_X_TOOLKIT
9874 static XrmOptionDescRec emacs_options
[] = {
9875 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
9876 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
9878 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9879 XrmoptionSepArg
, NULL
},
9880 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
9882 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9883 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9884 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9885 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
9886 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
9887 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
9888 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
9891 /* Whether atimer for Xt timeouts is activated or not. */
9893 static int x_timeout_atimer_activated_flag
;
9895 #endif /* USE_X_TOOLKIT */
9897 static int x_initialized
;
9899 /* Test whether two display-name strings agree up to the dot that separates
9900 the screen number from the server number. */
9902 same_x_server (const char *name1
, const char *name2
)
9905 const char *system_name
= SSDATA (Vsystem_name
);
9906 ptrdiff_t system_name_length
= SBYTES (Vsystem_name
);
9907 ptrdiff_t length_until_period
= 0;
9909 while (system_name
[length_until_period
] != 0
9910 && system_name
[length_until_period
] != '.')
9911 length_until_period
++;
9913 /* Treat `unix' like an empty host name. */
9914 if (! strncmp (name1
, "unix:", 5))
9916 if (! strncmp (name2
, "unix:", 5))
9918 /* Treat this host's name like an empty host name. */
9919 if (! strncmp (name1
, system_name
, system_name_length
)
9920 && name1
[system_name_length
] == ':')
9921 name1
+= system_name_length
;
9922 if (! strncmp (name2
, system_name
, system_name_length
)
9923 && name2
[system_name_length
] == ':')
9924 name2
+= system_name_length
;
9925 /* Treat this host's domainless name like an empty host name. */
9926 if (! strncmp (name1
, system_name
, length_until_period
)
9927 && name1
[length_until_period
] == ':')
9928 name1
+= length_until_period
;
9929 if (! strncmp (name2
, system_name
, length_until_period
)
9930 && name2
[length_until_period
] == ':')
9931 name2
+= length_until_period
;
9933 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
9937 if (seen_colon
&& *name1
== '.')
9941 && (*name1
== '.' || *name1
== '\0')
9942 && (*name2
== '.' || *name2
== '\0'));
9945 /* Count number of set bits in mask and number of bits to shift to
9946 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9949 get_bits_and_offset (long unsigned int mask
, int *bits
, int *offset
)
9970 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9971 But don't permanently open it, just test its availability. */
9974 x_display_ok (const char *display
)
9979 dpy
= XOpenDisplay (display
);
9981 XCloseDisplay (dpy
);
9989 my_log_handler (const gchar
*log_domain
, GLogLevelFlags log_level
,
9990 const gchar
*msg
, gpointer user_data
)
9992 if (!strstr (msg
, "g_set_prgname"))
9993 fprintf (stderr
, "%s-WARNING **: %s\n", log_domain
, msg
);
9997 /* Open a connection to X display DISPLAY_NAME, and return
9998 the structure that describes the open display.
9999 If we cannot contact the display, return null. */
10001 struct x_display_info
*
10002 x_term_init (Lisp_Object display_name
, char *xrm_option
, char *resource_name
)
10006 struct terminal
*terminal
;
10007 struct x_display_info
*dpyinfo
;
10009 Mouse_HLInfo
*hlinfo
;
10014 if (!x_initialized
)
10020 if (! x_display_ok (SSDATA (display_name
)))
10021 error ("Display %s can't be opened", SSDATA (display_name
));
10025 #define NUM_ARGV 10
10027 char *argv
[NUM_ARGV
];
10028 char **argv2
= argv
;
10031 if (x_initialized
++ > 1)
10033 xg_display_open (SSDATA (display_name
), &dpy
);
10037 static char display_opt
[] = "--display";
10038 static char name_opt
[] = "--name";
10040 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
10044 argv
[argc
++] = initial_argv
[0];
10046 if (! NILP (display_name
))
10048 argv
[argc
++] = display_opt
;
10049 argv
[argc
++] = SSDATA (display_name
);
10052 argv
[argc
++] = name_opt
;
10053 argv
[argc
++] = resource_name
;
10055 XSetLocaleModifiers ("");
10057 /* Emacs can only handle core input events, so make sure
10058 Gtk doesn't use Xinput or Xinput2 extensions. */
10060 static char fix_events
[] = "GDK_CORE_DEVICE_EVENTS=1";
10061 putenv (fix_events
);
10064 /* Work around GLib bug that outputs a faulty warning. See
10065 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
10066 id
= g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING
| G_LOG_FLAG_FATAL
10067 | G_LOG_FLAG_RECURSION
, my_log_handler
, NULL
);
10069 /* NULL window -> events for all windows go to our function.
10070 Call before gtk_init so Gtk+ event filters comes after our. */
10071 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
10073 gtk_init (&argc
, &argv2
);
10074 g_log_remove_handler ("GLib", id
);
10076 /* gtk_init does set_locale. We must fix locale after calling it. */
10080 dpy
= DEFAULT_GDK_DISPLAY ();
10082 #if GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION <= 90
10083 /* Load our own gtkrc if it exists. */
10085 const char *file
= "~/.emacs.d/gtkrc";
10086 Lisp_Object s
, abs_file
;
10088 s
= make_string (file
, strlen (file
));
10089 abs_file
= Fexpand_file_name (s
, Qnil
);
10091 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
10092 gtk_rc_parse (SSDATA (abs_file
));
10096 XSetErrorHandler (x_error_handler
);
10097 XSetIOErrorHandler (x_io_error_quitter
);
10100 #else /* not USE_GTK */
10101 #ifdef USE_X_TOOLKIT
10102 /* weiner@footloose.sps.mot.com reports that this causes
10104 X protocol error: BadAtom (invalid Atom parameter)
10105 on protocol request 18skiloaf.
10106 So let's not use it until R6. */
10107 #ifdef HAVE_X11XTR6
10108 XtSetLanguageProc (NULL
, NULL
, NULL
);
10119 argv
[argc
++] = "-xrm";
10120 argv
[argc
++] = xrm_option
;
10122 turn_on_atimers (0);
10123 dpy
= XtOpenDisplay (Xt_app_con
, SSDATA (display_name
),
10124 resource_name
, EMACS_CLASS
,
10125 emacs_options
, XtNumber (emacs_options
),
10127 turn_on_atimers (1);
10129 #ifdef HAVE_X11XTR6
10130 /* I think this is to compensate for XtSetLanguageProc. */
10135 #else /* not USE_X_TOOLKIT */
10136 XSetLocaleModifiers ("");
10137 dpy
= XOpenDisplay (SSDATA (display_name
));
10138 #endif /* not USE_X_TOOLKIT */
10139 #endif /* not USE_GTK*/
10141 /* Detect failure. */
10148 /* We have definitely succeeded. Record the new connection. */
10150 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
10151 memset (dpyinfo
, 0, sizeof *dpyinfo
);
10152 hlinfo
= &dpyinfo
->mouse_highlight
;
10154 terminal
= x_create_terminal (dpyinfo
);
10157 struct x_display_info
*share
;
10160 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
10161 share
= share
->next
, tail
= XCDR (tail
))
10162 if (same_x_server (SSDATA (XCAR (XCAR (tail
))),
10163 SSDATA (display_name
)))
10166 terminal
->kboard
= share
->terminal
->kboard
;
10169 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
10170 init_kboard (terminal
->kboard
);
10171 KVAR (terminal
->kboard
, Vwindow_system
) = Qx
;
10173 /* Add the keyboard to the list before running Lisp code (via
10174 Qvendor_specific_keysyms below), since these are not traced
10175 via terminals but only through all_kboards. */
10176 terminal
->kboard
->next_kboard
= all_kboards
;
10177 all_kboards
= terminal
->kboard
;
10179 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
10181 char *vendor
= ServerVendor (dpy
);
10183 /* Protect terminal from GC before removing it from the
10184 list of terminals. */
10185 struct gcpro gcpro1
;
10186 Lisp_Object gcpro_term
;
10187 XSETTERMINAL (gcpro_term
, terminal
);
10188 GCPRO1 (gcpro_term
);
10190 /* Temporarily hide the partially initialized terminal. */
10191 terminal_list
= terminal
->next_terminal
;
10193 KVAR (terminal
->kboard
, Vsystem_key_alist
)
10194 = call1 (Qvendor_specific_keysyms
,
10195 vendor
? build_string (vendor
) : empty_unibyte_string
);
10197 terminal
->next_terminal
= terminal_list
;
10198 terminal_list
= terminal
;
10202 /* Don't let the initial kboard remain current longer than necessary.
10203 That would cause problems if a file loaded on startup tries to
10204 prompt in the mini-buffer. */
10205 if (current_kboard
== initial_kboard
)
10206 current_kboard
= terminal
->kboard
;
10208 terminal
->kboard
->reference_count
++;
10211 /* Put this display on the chain. */
10212 dpyinfo
->next
= x_display_list
;
10213 x_display_list
= dpyinfo
;
10215 /* Put it on x_display_name_list as well, to keep them parallel. */
10216 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
10217 x_display_name_list
);
10218 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10220 dpyinfo
->display
= dpy
;
10222 /* Set the name of the terminal. */
10223 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
10224 memcpy (terminal
->name
, SSDATA (display_name
), SBYTES (display_name
));
10225 terminal
->name
[SBYTES (display_name
)] = 0;
10228 XSetAfterFunction (x_current_display
, x_trace_wire
);
10231 lim
= min (PTRDIFF_MAX
, SIZE_MAX
) - sizeof "@";
10232 if (lim
- SBYTES (Vinvocation_name
) < SBYTES (Vsystem_name
))
10233 memory_full (SIZE_MAX
);
10235 = (char *) xmalloc (SBYTES (Vinvocation_name
)
10236 + SBYTES (Vsystem_name
)
10238 strcat (strcat (strcpy (dpyinfo
->x_id_name
, SSDATA (Vinvocation_name
)), "@"),
10239 SSDATA (Vsystem_name
));
10241 /* Figure out which modifier bits mean what. */
10242 x_find_modifier_meanings (dpyinfo
);
10244 /* Get the scroll bar cursor. */
10246 /* We must create a GTK cursor, it is required for GTK widgets. */
10247 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10248 #endif /* USE_GTK */
10250 dpyinfo
->vertical_scroll_bar_cursor
10251 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10253 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10254 resource_name
, EMACS_CLASS
);
10255 #ifdef HAVE_XRMSETDATABASE
10256 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10258 dpyinfo
->display
->db
= xrdb
;
10260 /* Put the rdb where we can find it in a way that works on
10262 dpyinfo
->xrdb
= xrdb
;
10264 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10265 DefaultScreen (dpyinfo
->display
));
10266 select_visual (dpyinfo
);
10267 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10268 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10269 dpyinfo
->client_leader_window
= 0;
10270 dpyinfo
->grabbed
= 0;
10271 dpyinfo
->reference_count
= 0;
10272 dpyinfo
->icon_bitmap_id
= -1;
10273 dpyinfo
->n_fonts
= 0;
10274 dpyinfo
->bitmaps
= 0;
10275 dpyinfo
->bitmaps_size
= 0;
10276 dpyinfo
->bitmaps_last
= 0;
10277 dpyinfo
->scratch_cursor_gc
= 0;
10278 hlinfo
->mouse_face_mouse_frame
= 0;
10279 hlinfo
->mouse_face_deferred_gc
= 0;
10280 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
10281 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
10282 hlinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10283 hlinfo
->mouse_face_window
= Qnil
;
10284 hlinfo
->mouse_face_overlay
= Qnil
;
10285 hlinfo
->mouse_face_mouse_x
= hlinfo
->mouse_face_mouse_y
= 0;
10286 hlinfo
->mouse_face_defer
= 0;
10287 hlinfo
->mouse_face_hidden
= 0;
10288 dpyinfo
->x_focus_frame
= 0;
10289 dpyinfo
->x_focus_event_frame
= 0;
10290 dpyinfo
->x_highlight_frame
= 0;
10291 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10293 /* See if we can construct pixel values from RGB values. */
10294 dpyinfo
->red_bits
= dpyinfo
->blue_bits
= dpyinfo
->green_bits
= 0;
10295 dpyinfo
->red_offset
= dpyinfo
->blue_offset
= dpyinfo
->green_offset
= 0;
10297 if (dpyinfo
->visual
->class == TrueColor
)
10299 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10300 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10301 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10302 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10303 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10304 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10307 /* See if a private colormap is requested. */
10308 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10310 if (dpyinfo
->visual
->class == PseudoColor
)
10313 value
= display_x_get_resource (dpyinfo
,
10314 build_string ("privateColormap"),
10315 build_string ("PrivateColormap"),
10317 if (STRINGP (value
)
10318 && (!strcmp (SSDATA (value
), "true")
10319 || !strcmp (SSDATA (value
), "on")))
10320 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10324 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10325 dpyinfo
->visual
, AllocNone
);
10329 /* If we are using Xft, check dpi value in X resources.
10330 It is better we use it as well, since Xft will use it, as will all
10331 Gnome applications. If our real DPI is smaller or larger than the
10332 one Xft uses, our font will look smaller or larger than other
10333 for other applications, even if it is the same font name (monospace-10
10335 char *v
= XGetDefault (dpyinfo
->display
, "Xft", "dpi");
10337 if (v
!= NULL
&& sscanf (v
, "%lf", &d
) == 1)
10338 dpyinfo
->resy
= dpyinfo
->resx
= d
;
10342 if (dpyinfo
->resy
< 1)
10344 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10345 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10346 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10347 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10348 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10349 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10350 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10351 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10352 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10361 { "WM_PROTOCOLS", &dpyinfo
->Xatom_wm_protocols
},
10362 { "WM_TAKE_FOCUS", &dpyinfo
->Xatom_wm_take_focus
},
10363 { "WM_SAVE_YOURSELF", &dpyinfo
->Xatom_wm_save_yourself
},
10364 { "WM_DELETE_WINDOW", &dpyinfo
->Xatom_wm_delete_window
},
10365 { "WM_CHANGE_STATE", &dpyinfo
->Xatom_wm_change_state
},
10366 { "WM_CONFIGURE_DENIED", &dpyinfo
->Xatom_wm_configure_denied
},
10367 { "WM_MOVED", &dpyinfo
->Xatom_wm_window_moved
},
10368 { "WM_CLIENT_LEADER", &dpyinfo
->Xatom_wm_client_leader
},
10369 { "Editres", &dpyinfo
->Xatom_editres
},
10370 { "CLIPBOARD", &dpyinfo
->Xatom_CLIPBOARD
},
10371 { "TIMESTAMP", &dpyinfo
->Xatom_TIMESTAMP
},
10372 { "TEXT", &dpyinfo
->Xatom_TEXT
},
10373 { "COMPOUND_TEXT", &dpyinfo
->Xatom_COMPOUND_TEXT
},
10374 { "UTF8_STRING", &dpyinfo
->Xatom_UTF8_STRING
},
10375 { "DELETE", &dpyinfo
->Xatom_DELETE
},
10376 { "MULTIPLE", &dpyinfo
->Xatom_MULTIPLE
},
10377 { "INCR", &dpyinfo
->Xatom_INCR
},
10378 { "_EMACS_TMP_", &dpyinfo
->Xatom_EMACS_TMP
},
10379 { "TARGETS", &dpyinfo
->Xatom_TARGETS
},
10380 { "NULL", &dpyinfo
->Xatom_NULL
},
10381 { "ATOM", &dpyinfo
->Xatom_ATOM
},
10382 { "ATOM_PAIR", &dpyinfo
->Xatom_ATOM_PAIR
},
10383 { "CLIPBOARD_MANAGER", &dpyinfo
->Xatom_CLIPBOARD_MANAGER
},
10384 { "_XEMBED_INFO", &dpyinfo
->Xatom_XEMBED_INFO
},
10385 /* For properties of font. */
10386 { "PIXEL_SIZE", &dpyinfo
->Xatom_PIXEL_SIZE
},
10387 { "AVERAGE_WIDTH", &dpyinfo
->Xatom_AVERAGE_WIDTH
},
10388 { "_MULE_BASELINE_OFFSET", &dpyinfo
->Xatom_MULE_BASELINE_OFFSET
},
10389 { "_MULE_RELATIVE_COMPOSE", &dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
},
10390 { "_MULE_DEFAULT_ASCENT", &dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
},
10391 /* Ghostscript support. */
10392 { "DONE", &dpyinfo
->Xatom_DONE
},
10393 { "PAGE", &dpyinfo
->Xatom_PAGE
},
10394 { "SCROLLBAR", &dpyinfo
->Xatom_Scrollbar
},
10395 { "_XEMBED", &dpyinfo
->Xatom_XEMBED
},
10397 { "_NET_WM_STATE", &dpyinfo
->Xatom_net_wm_state
},
10398 { "_NET_WM_STATE_FULLSCREEN", &dpyinfo
->Xatom_net_wm_state_fullscreen
},
10399 { "_NET_WM_STATE_MAXIMIZED_HORZ",
10400 &dpyinfo
->Xatom_net_wm_state_maximized_horz
},
10401 { "_NET_WM_STATE_MAXIMIZED_VERT",
10402 &dpyinfo
->Xatom_net_wm_state_maximized_vert
},
10403 { "_NET_WM_STATE_STICKY", &dpyinfo
->Xatom_net_wm_state_sticky
},
10404 { "_NET_WM_STATE_HIDDEN", &dpyinfo
->Xatom_net_wm_state_hidden
},
10405 { "_NET_WM_WINDOW_TYPE", &dpyinfo
->Xatom_net_window_type
},
10406 { "_NET_WM_WINDOW_TYPE_TOOLTIP",
10407 &dpyinfo
->Xatom_net_window_type_tooltip
},
10408 { "_NET_WM_ICON_NAME", &dpyinfo
->Xatom_net_wm_icon_name
},
10409 { "_NET_WM_NAME", &dpyinfo
->Xatom_net_wm_name
},
10410 { "_NET_SUPPORTED", &dpyinfo
->Xatom_net_supported
},
10411 { "_NET_SUPPORTING_WM_CHECK", &dpyinfo
->Xatom_net_supporting_wm_check
},
10412 { "_NET_WM_WINDOW_OPACITY", &dpyinfo
->Xatom_net_wm_window_opacity
},
10413 { "_NET_ACTIVE_WINDOW", &dpyinfo
->Xatom_net_active_window
},
10414 { "_NET_FRAME_EXTENTS", &dpyinfo
->Xatom_net_frame_extents
},
10415 /* Session management */
10416 { "SM_CLIENT_ID", &dpyinfo
->Xatom_SM_CLIENT_ID
},
10417 { "_XSETTINGS_SETTINGS", &dpyinfo
->Xatom_xsettings_prop
},
10418 { "MANAGER", &dpyinfo
->Xatom_xsettings_mgr
},
10422 const int atom_count
= sizeof (atom_refs
) / sizeof (atom_refs
[0]);
10423 /* 1 for _XSETTINGS_SN */
10424 const int total_atom_count
= 1 + atom_count
;
10425 Atom
*atoms_return
= xmalloc (sizeof (Atom
) * total_atom_count
);
10426 char **atom_names
= xmalloc (sizeof (char *) * total_atom_count
);
10427 char xsettings_atom_name
[64];
10429 for (i
= 0; i
< atom_count
; i
++)
10430 atom_names
[i
] = (char *) atom_refs
[i
].name
;
10432 /* Build _XSETTINGS_SN atom name */
10433 snprintf (xsettings_atom_name
, sizeof (xsettings_atom_name
),
10434 "_XSETTINGS_S%d", XScreenNumberOfScreen (dpyinfo
->screen
));
10435 atom_names
[i
] = xsettings_atom_name
;
10437 XInternAtoms (dpyinfo
->display
, atom_names
, total_atom_count
,
10438 False
, atoms_return
);
10440 for (i
= 0; i
< atom_count
; i
++)
10441 *atom_refs
[i
].atom
= atoms_return
[i
];
10443 /* Manual copy of last atom */
10444 dpyinfo
->Xatom_xsettings_sel
= atoms_return
[i
];
10446 xfree (atom_names
);
10447 xfree (atoms_return
);
10450 dpyinfo
->x_dnd_atoms_size
= 8;
10451 dpyinfo
->x_dnd_atoms_length
= 0;
10452 dpyinfo
->x_dnd_atoms
= xmalloc (sizeof (*dpyinfo
->x_dnd_atoms
)
10453 * dpyinfo
->x_dnd_atoms_size
);
10455 dpyinfo
->net_supported_atoms
= NULL
;
10456 dpyinfo
->nr_net_supported_atoms
= 0;
10457 dpyinfo
->net_supported_window
= 0;
10459 connection
= ConnectionNumber (dpyinfo
->display
);
10460 dpyinfo
->connection
= connection
;
10464 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10465 gray_bits
, gray_width
, gray_height
,
10470 xim_initialize (dpyinfo
, resource_name
);
10473 xsettings_initialize (dpyinfo
);
10475 /* This is only needed for distinguishing keyboard and process input. */
10476 if (connection
!= 0)
10477 add_keyboard_wait_descriptor (connection
);
10480 fcntl (connection
, F_SETOWN
, getpid ());
10481 #endif /* ! defined (F_SETOWN) */
10484 if (interrupt_input
)
10485 init_sigio (connection
);
10486 #endif /* ! defined (SIGIO) */
10490 XrmValue d
, fr
, to
;
10493 dpy
= dpyinfo
->display
;
10494 d
.addr
= (XPointer
)&dpy
;
10495 d
.size
= sizeof (Display
*);
10496 fr
.addr
= XtDefaultFont
;
10497 fr
.size
= sizeof (XtDefaultFont
);
10498 to
.size
= sizeof (Font
*);
10499 to
.addr
= (XPointer
)&font
;
10500 x_catch_errors (dpy
);
10501 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10503 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
10504 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10505 x_uncatch_errors ();
10509 /* See if we should run in synchronous mode. This is useful
10510 for debugging X code. */
10513 value
= display_x_get_resource (dpyinfo
,
10514 build_string ("synchronous"),
10515 build_string ("Synchronous"),
10517 if (STRINGP (value
)
10518 && (!strcmp (SSDATA (value
), "true")
10519 || !strcmp (SSDATA (value
), "on")))
10520 XSynchronize (dpyinfo
->display
, True
);
10525 value
= display_x_get_resource (dpyinfo
,
10526 build_string ("useXIM"),
10527 build_string ("UseXIM"),
10530 if (STRINGP (value
)
10531 && (!strcmp (SSDATA (value
), "false")
10532 || !strcmp (SSDATA (value
), "off")))
10535 if (STRINGP (value
)
10536 && (!strcmp (SSDATA (value
), "true")
10537 || !strcmp (SSDATA (value
), "on")))
10543 /* Only do this for the very first display in the Emacs session.
10544 Ignore X session management when Emacs was first started on a
10546 if (terminal
->id
== 1)
10547 x_session_initialize (dpyinfo
);
10555 /* Get rid of display DPYINFO, deleting all frames on it,
10556 and without sending any more commands to the X server. */
10559 x_delete_display (struct x_display_info
*dpyinfo
)
10561 struct terminal
*t
;
10563 /* Close all frames and delete the generic struct terminal for this
10565 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
10566 if (t
->type
== output_x_window
&& t
->display_info
.x
== dpyinfo
)
10569 /* Close X session management when we close its display. */
10570 if (t
->id
== 1 && x_session_have_connection ())
10571 x_session_close ();
10573 delete_terminal (t
);
10577 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
10579 /* Discard this display from x_display_name_list and x_display_list.
10580 We can't use Fdelq because that can quit. */
10581 if (! NILP (x_display_name_list
)
10582 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10583 x_display_name_list
= XCDR (x_display_name_list
);
10588 tail
= x_display_name_list
;
10589 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10591 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10593 XSETCDR (tail
, XCDR (XCDR (tail
)));
10596 tail
= XCDR (tail
);
10600 if (next_noop_dpyinfo
== dpyinfo
)
10601 next_noop_dpyinfo
= dpyinfo
->next
;
10603 if (x_display_list
== dpyinfo
)
10604 x_display_list
= dpyinfo
->next
;
10607 struct x_display_info
*tail
;
10609 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10610 if (tail
->next
== dpyinfo
)
10611 tail
->next
= tail
->next
->next
;
10614 xfree (dpyinfo
->x_id_name
);
10615 xfree (dpyinfo
->x_dnd_atoms
);
10616 xfree (dpyinfo
->color_cells
);
10620 #ifdef USE_X_TOOLKIT
10622 /* Atimer callback function for TIMER. Called every 0.1s to process
10623 Xt timeouts, if needed. We must avoid calling XtAppPending as
10624 much as possible because that function does an implicit XFlush
10625 that slows us down. */
10628 x_process_timeouts (struct atimer
*timer
)
10631 x_timeout_atimer_activated_flag
= 0;
10632 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10634 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10635 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10636 /* Reactivate the atimer for next time. */
10637 x_activate_timeout_atimer ();
10642 /* Install an asynchronous timer that processes Xt timeout events
10643 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10644 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10645 function whenever these variables are set. This is necessary
10646 because some widget sets use timeouts internally, for example the
10647 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10648 processed, these widgets don't behave normally. */
10651 x_activate_timeout_atimer (void)
10654 if (!x_timeout_atimer_activated_flag
)
10656 EMACS_TIME interval
;
10658 EMACS_SET_SECS_USECS (interval
, 0, 100000);
10659 start_atimer (ATIMER_RELATIVE
, interval
, x_process_timeouts
, 0);
10660 x_timeout_atimer_activated_flag
= 1;
10665 #endif /* USE_X_TOOLKIT */
10668 /* Set up use of X before we make the first connection. */
10670 extern frame_parm_handler x_frame_parm_handlers
[];
10672 static struct redisplay_interface x_redisplay_interface
=
10674 x_frame_parm_handlers
,
10678 x_clear_end_of_line
,
10680 x_after_update_window_line
,
10681 x_update_window_begin
,
10682 x_update_window_end
,
10688 0, /* flush_display_optional */
10690 x_clear_window_mouse_face
,
10691 x_get_glyph_overhangs
,
10692 x_fix_overlapping_area
,
10693 x_draw_fringe_bitmap
,
10694 0, /* define_fringe_bitmap */
10695 0, /* destroy_fringe_bitmap */
10696 x_compute_glyph_string_overhangs
,
10697 x_draw_glyph_string
,
10698 x_define_frame_cursor
,
10699 x_clear_frame_area
,
10700 x_draw_window_cursor
,
10701 x_draw_vertical_window_border
,
10702 x_shift_glyphs_for_insert
10706 /* This function is called when the last frame on a display is deleted. */
10708 x_delete_terminal (struct terminal
*terminal
)
10710 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
10712 /* Protect against recursive calls. delete_frame in
10713 delete_terminal calls us back when it deletes our last frame. */
10714 if (!terminal
->name
)
10719 /* We must close our connection to the XIM server before closing the
10722 xim_close_dpy (dpyinfo
);
10725 /* If called from x_connection_closed, the display may already be closed
10726 and dpyinfo->display was set to 0 to indicate that. */
10727 if (dpyinfo
->display
)
10729 x_destroy_all_bitmaps (dpyinfo
);
10730 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
10732 /* Whether or not XCloseDisplay destroys the associated resource
10733 database depends on the version of libX11. To avoid both
10734 crash and memory leak, we dissociate the database from the
10735 display and then destroy dpyinfo->xrdb ourselves.
10737 Unfortunately, the above strategy does not work in some
10738 situations due to a bug in newer versions of libX11: because
10739 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
10740 dpy->db is NULL, XCloseDisplay destroys the associated
10741 database whereas it has not been created by XGetDefault
10742 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
10743 don't destroy the database here in order to avoid the crash
10744 in the above situations for now, though that may cause memory
10745 leaks in other situations. */
10747 #ifdef HAVE_XRMSETDATABASE
10748 XrmSetDatabase (dpyinfo
->display
, NULL
);
10750 dpyinfo
->display
->db
= NULL
;
10752 /* We used to call XrmDestroyDatabase from x_delete_display, but
10753 some older versions of libX11 crash if we call it after
10754 closing all the displays. */
10755 XrmDestroyDatabase (dpyinfo
->xrdb
);
10759 xg_display_close (dpyinfo
->display
);
10761 #ifdef USE_X_TOOLKIT
10762 XtCloseDisplay (dpyinfo
->display
);
10764 XCloseDisplay (dpyinfo
->display
);
10766 #endif /* ! USE_GTK */
10769 /* Mark as dead. */
10770 dpyinfo
->display
= NULL
;
10771 x_delete_display (dpyinfo
);
10775 /* Create a struct terminal, initialize it with the X11 specific
10776 functions and make DISPLAY->TERMINAL point to it. */
10778 static struct terminal
*
10779 x_create_terminal (struct x_display_info
*dpyinfo
)
10781 struct terminal
*terminal
;
10783 terminal
= create_terminal ();
10785 terminal
->type
= output_x_window
;
10786 terminal
->display_info
.x
= dpyinfo
;
10787 dpyinfo
->terminal
= terminal
;
10789 /* kboard is initialized in x_term_init. */
10791 terminal
->clear_frame_hook
= x_clear_frame
;
10792 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
10793 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
10794 terminal
->ring_bell_hook
= XTring_bell
;
10795 terminal
->toggle_invisible_pointer_hook
= XTtoggle_invisible_pointer
;
10796 terminal
->reset_terminal_modes_hook
= XTreset_terminal_modes
;
10797 terminal
->set_terminal_modes_hook
= XTset_terminal_modes
;
10798 terminal
->update_begin_hook
= x_update_begin
;
10799 terminal
->update_end_hook
= x_update_end
;
10800 terminal
->set_terminal_window_hook
= XTset_terminal_window
;
10801 terminal
->read_socket_hook
= XTread_socket
;
10802 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
10803 terminal
->mouse_position_hook
= XTmouse_position
;
10804 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
10805 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
10806 terminal
->fullscreen_hook
= XTfullscreen_hook
;
10807 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10808 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10809 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10810 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10812 terminal
->delete_frame_hook
= x_destroy_window
;
10813 terminal
->delete_terminal_hook
= x_delete_terminal
;
10815 terminal
->rif
= &x_redisplay_interface
;
10816 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
10817 terminal
->char_ins_del_ok
= 1;
10818 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
10819 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
10820 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
10827 x_initialize (void)
10832 last_tool_bar_item
= -1;
10833 any_help_event_p
= 0;
10834 ignore_next_mouse_click_timeout
= 0;
10837 current_count
= -1;
10840 /* Try to use interrupt input; if we can't, then start polling. */
10841 Fset_input_interrupt_mode (Qt
);
10843 #ifdef USE_X_TOOLKIT
10844 XtToolkitInitialize ();
10846 Xt_app_con
= XtCreateApplicationContext ();
10848 /* Register a converter from strings to pixels, which uses
10849 Emacs' color allocation infrastructure. */
10850 XtAppSetTypeConverter (Xt_app_con
,
10851 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10852 cvt_string_to_pixel_args
,
10853 XtNumber (cvt_string_to_pixel_args
),
10854 XtCacheByDisplay
, cvt_pixel_dtor
);
10856 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10859 #ifdef USE_TOOLKIT_SCROLL_BARS
10861 xaw3d_arrow_scroll
= False
;
10862 xaw3d_pick_top
= True
;
10866 pending_autoraise_frame
= 0;
10867 pending_event_wait
.f
= 0;
10868 pending_event_wait
.eventtype
= 0;
10870 /* Note that there is no real way portable across R3/R4 to get the
10871 original error handler. */
10872 XSetErrorHandler (x_error_handler
);
10873 XSetIOErrorHandler (x_io_error_quitter
);
10875 signal (SIGPIPE
, x_connection_signal
);
10877 xgselect_initialize ();
10882 syms_of_xterm (void)
10884 x_error_message
= NULL
;
10886 staticpro (&x_display_name_list
);
10887 x_display_name_list
= Qnil
;
10889 staticpro (&last_mouse_scroll_bar
);
10890 last_mouse_scroll_bar
= Qnil
;
10892 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
10893 DEFSYM (Qlatin_1
, "latin-1");
10895 staticpro (&last_mouse_press_frame
);
10896 last_mouse_press_frame
= Qnil
;
10899 xg_default_icon_file
= make_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
10900 staticpro (&xg_default_icon_file
);
10902 DEFSYM (Qx_gtk_map_stock
, "x-gtk-map-stock");
10905 DEFVAR_BOOL ("x-use-underline-position-properties",
10906 x_use_underline_position_properties
,
10907 doc
: /* Non-nil means make use of UNDERLINE_POSITION font properties.
10908 A value of nil means ignore them. If you encounter fonts with bogus
10909 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10910 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10911 to override the font's UNDERLINE_POSITION for small font display
10913 x_use_underline_position_properties
= 1;
10915 DEFVAR_BOOL ("x-underline-at-descent-line",
10916 x_underline_at_descent_line
,
10917 doc
: /* Non-nil means to draw the underline at the same place as the descent line.
10918 A value of nil means to draw the underline according to the value of the
10919 variable `x-use-underline-position-properties', which is usually at the
10920 baseline level. The default value is nil. */);
10921 x_underline_at_descent_line
= 0;
10923 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10924 x_mouse_click_focus_ignore_position
,
10925 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
10926 This variable is only used when the window manager requires that you
10927 click on a frame to select it (give it focus). In that case, a value
10928 of nil, means that the selected window and cursor position changes to
10929 reflect the mouse click position, while a non-nil value means that the
10930 selected window or cursor position is preserved. */);
10931 x_mouse_click_focus_ignore_position
= 0;
10933 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars
,
10934 doc
: /* Which toolkit scroll bars Emacs uses, if any.
10935 A value of nil means Emacs doesn't use toolkit scroll bars.
10936 With the X Window system, the value is a symbol describing the
10937 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
10938 With MS Windows or Nextstep, the value is t. */);
10939 #ifdef USE_TOOLKIT_SCROLL_BARS
10941 Vx_toolkit_scroll_bars
= intern_c_string ("motif");
10942 #elif defined HAVE_XAW3D
10943 Vx_toolkit_scroll_bars
= intern_c_string ("xaw3d");
10945 Vx_toolkit_scroll_bars
= intern_c_string ("gtk");
10947 Vx_toolkit_scroll_bars
= intern_c_string ("xaw");
10950 Vx_toolkit_scroll_bars
= Qnil
;
10953 staticpro (&last_mouse_motion_frame
);
10954 last_mouse_motion_frame
= Qnil
;
10956 Qmodifier_value
= intern_c_string ("modifier-value");
10957 Qalt
= intern_c_string ("alt");
10958 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10959 Qhyper
= intern_c_string ("hyper");
10960 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10961 Qmeta
= intern_c_string ("meta");
10962 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10963 Qsuper
= intern_c_string ("super");
10964 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10966 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym
,
10967 doc
: /* Which keys Emacs uses for the alt modifier.
10968 This should be one of the symbols `alt', `hyper', `meta', `super'.
10969 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10970 is nil, which is the same as `alt'. */);
10971 Vx_alt_keysym
= Qnil
;
10973 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym
,
10974 doc
: /* Which keys Emacs uses for the hyper modifier.
10975 This should be one of the symbols `alt', `hyper', `meta', `super'.
10976 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10977 default is nil, which is the same as `hyper'. */);
10978 Vx_hyper_keysym
= Qnil
;
10980 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym
,
10981 doc
: /* Which keys Emacs uses for the meta modifier.
10982 This should be one of the symbols `alt', `hyper', `meta', `super'.
10983 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10984 default is nil, which is the same as `meta'. */);
10985 Vx_meta_keysym
= Qnil
;
10987 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym
,
10988 doc
: /* Which keys Emacs uses for the super modifier.
10989 This should be one of the symbols `alt', `hyper', `meta', `super'.
10990 For example, `super' means use the Super_L and Super_R keysyms. The
10991 default is nil, which is the same as `super'. */);
10992 Vx_super_keysym
= Qnil
;
10994 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table
,
10995 doc
: /* Hash table of character codes indexed by X keysym codes. */);
10996 Vx_keysym_table
= make_hash_table (Qeql
, make_number (900),
10997 make_float (DEFAULT_REHASH_SIZE
),
10998 make_float (DEFAULT_REHASH_THRESHOLD
),
11002 #endif /* HAVE_X_WINDOWS */