1 /* X Communication module for terminals which understand the X protocol.
3 Copyright (C) 1989, 1993-2014 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. */
27 #include "blockinput.h"
28 #include "syssignal.h"
30 /* This may include sys/types.h, and that somehow loses
31 if this is not done before the other system files. */
33 #include <X11/cursorfont.h>
35 /* If we have Xfixes extension, use it for pointer blanking. */
37 #include <X11/extensions/Xfixes.h>
40 /* Using Xft implies that XRender is available. */
42 #include <X11/extensions/Xrender.h>
45 /* Load sys/types.h if not already loaded.
46 In some systems loading it twice is suicidal. */
48 #include <sys/types.h>
51 #include <sys/ioctl.h>
58 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
59 /* #include <sys/param.h> */
62 #include "character.h"
65 #include "dispextern.h"
67 #include "termhooks.h"
70 #include "emacs-icon.h"
75 #include "intervals.h"
80 #include "xsettings.h"
82 #include "sysselect.h"
86 #include <X11/Shell.h>
94 #include <X11/Xproto.h>
98 #if defined (USE_LUCID) || defined (USE_MOTIF)
99 #include "../lwlib/xlwmenu.h"
103 #if !defined (NO_EDITRES)
105 extern void _XEditResCheckMessages (Widget
, XtPointer
, XEvent
*, Boolean
*);
106 #endif /* not NO_EDITRES */
108 /* Include toolkit specific headers for the scroll bar widget. */
110 #ifdef USE_TOOLKIT_SCROLL_BARS
111 #if defined USE_MOTIF
112 #include <Xm/Xm.h> /* For LESSTIF_VERSION */
113 #include <Xm/ScrollBar.h>
114 #else /* !USE_MOTIF i.e. use Xaw */
117 #include <X11/Xaw3d/Simple.h>
118 #include <X11/Xaw3d/Scrollbar.h>
119 #include <X11/Xaw3d/ThreeD.h>
120 #else /* !HAVE_XAW3D */
121 #include <X11/Xaw/Simple.h>
122 #include <X11/Xaw/Scrollbar.h>
123 #endif /* !HAVE_XAW3D */
125 #define XtNpickTop "pickTop"
126 #endif /* !XtNpickTop */
127 #endif /* !USE_MOTIF */
128 #endif /* USE_TOOLKIT_SCROLL_BARS */
130 #endif /* USE_X_TOOLKIT */
134 #ifndef XtNinitialState
135 #define XtNinitialState "initialState"
139 #include "bitmaps/gray.xbm"
142 #include <X11/XKBlib.h>
145 /* Default to using XIM if available. */
149 bool use_xim
= false; /* configure --without-xim */
152 /* Non-zero means that a HELP_EVENT has been generated since Emacs
155 static bool any_help_event_p
;
157 /* This is a chain of structures for all the X displays currently in
160 struct x_display_info
*x_display_list
;
164 /* The application context for Xt use. */
165 XtAppContext Xt_app_con
;
166 static String Xt_default_resources
[] = {0};
168 /* Non-zero means user is interacting with a toolkit scroll bar. */
169 static bool toolkit_scroll_bar_interaction
;
171 #endif /* USE_X_TOOLKIT */
173 /* Non-zero timeout value means ignore next mouse click if it arrives
174 before that timeout elapses (i.e. as part of the same sequence of
175 events resulting from clicking on a frame to select it). */
177 static Time ignore_next_mouse_click_timeout
;
179 /* Used locally within XTread_socket. */
181 static int x_noop_count
;
183 static Lisp_Object Qalt
, Qhyper
, Qmeta
, Qsuper
, Qmodifier_value
;
185 static Lisp_Object Qvendor_specific_keysyms
;
186 static Lisp_Object Qlatin_1
;
189 /* The name of the Emacs icon file. */
190 static Lisp_Object xg_default_icon_file
;
192 /* Used in gtkutil.c. */
193 Lisp_Object Qx_gtk_map_stock
;
196 /* Some functions take this as char *, not const char *. */
197 static char emacs_class
[] = EMACS_CLASS
;
201 XEMBED_MAPPED
= 1 << 0
206 XEMBED_EMBEDDED_NOTIFY
= 0,
207 XEMBED_WINDOW_ACTIVATE
= 1,
208 XEMBED_WINDOW_DEACTIVATE
= 2,
209 XEMBED_REQUEST_FOCUS
= 3,
211 XEMBED_FOCUS_OUT
= 5,
212 XEMBED_FOCUS_NEXT
= 6,
213 XEMBED_FOCUS_PREV
= 7,
215 XEMBED_MODALITY_ON
= 10,
216 XEMBED_MODALITY_OFF
= 11,
217 XEMBED_REGISTER_ACCELERATOR
= 12,
218 XEMBED_UNREGISTER_ACCELERATOR
= 13,
219 XEMBED_ACTIVATE_ACCELERATOR
= 14
222 static bool x_alloc_nearest_color_1 (Display
*, Colormap
, XColor
*);
223 static void x_set_window_size_1 (struct frame
*, int, int, int, bool);
224 static void x_raise_frame (struct frame
*);
225 static void x_lower_frame (struct frame
*);
226 static const XColor
*x_color_cells (Display
*, int *);
227 static int x_io_error_quitter (Display
*);
228 static struct terminal
*x_create_terminal (struct x_display_info
*);
229 void x_delete_terminal (struct terminal
*);
230 static void x_update_end (struct frame
*);
231 static void XTframe_up_to_date (struct frame
*);
232 static void x_clear_frame (struct frame
*);
233 static _Noreturn
void x_ins_del_lines (struct frame
*, int, int);
234 static void frame_highlight (struct frame
*);
235 static void frame_unhighlight (struct frame
*);
236 static void x_new_focus_frame (struct x_display_info
*, struct frame
*);
237 static void x_focus_changed (int, int, struct x_display_info
*,
238 struct frame
*, struct input_event
*);
239 static void XTframe_rehighlight (struct frame
*);
240 static void x_frame_rehighlight (struct x_display_info
*);
241 static void x_draw_hollow_cursor (struct window
*, struct glyph_row
*);
242 static void x_draw_bar_cursor (struct window
*, struct glyph_row
*, int,
243 enum text_cursor_kinds
);
245 static void x_clip_to_row (struct window
*, struct glyph_row
*,
246 enum glyph_row_area
, GC
);
247 static void x_flush (struct frame
*f
);
248 static void x_update_begin (struct frame
*);
249 static void x_update_window_begin (struct window
*);
250 static struct scroll_bar
*x_window_to_scroll_bar (Display
*, Window
);
251 static void x_scroll_bar_report_motion (struct frame
**, Lisp_Object
*,
252 enum scroll_bar_part
*,
253 Lisp_Object
*, Lisp_Object
*,
255 static int x_handle_net_wm_state (struct frame
*, const XPropertyEvent
*);
256 static void x_check_fullscreen (struct frame
*);
257 static void x_check_expected_move (struct frame
*, int, int);
258 static void x_sync_with_move (struct frame
*, int, int, int);
259 static int handle_one_xevent (struct x_display_info
*,
260 const XEvent
*, int *,
261 struct input_event
*);
262 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
263 static int x_dispatch_event (XEvent
*, Display
*);
265 /* Don't declare this _Noreturn because we want no
266 interference with debugging failing X calls. */
267 static void x_connection_closed (Display
*, const char *);
268 static void x_wm_set_window_state (struct frame
*, int);
269 static void x_wm_set_icon_pixmap (struct frame
*, ptrdiff_t);
270 static void x_initialize (void);
273 /* Flush display of frame F. */
276 x_flush (struct frame
*f
)
278 eassert (f
&& FRAME_X_P (f
));
279 /* Don't call XFlush when it is not safe to redisplay; the X
280 connection may be broken. */
281 if (!NILP (Vinhibit_redisplay
))
285 XFlush (FRAME_X_DISPLAY (f
));
290 /* Remove calls to XFlush by defining XFlush to an empty replacement.
291 Calls to XFlush should be unnecessary because the X output buffer
292 is flushed automatically as needed by calls to XPending,
293 XNextEvent, or XWindowEvent according to the XFlush man page.
294 XTread_socket calls XPending. Removing XFlush improves
297 #define XFlush(DISPLAY) (void) 0
300 /***********************************************************************
302 ***********************************************************************/
306 /* This is a function useful for recording debugging information about
307 the sequence of occurrences in this file. */
315 struct record event_record
[100];
317 int event_record_index
;
320 record_event (char *locus
, int type
)
322 if (event_record_index
== ARRAYELTS (event_record
))
323 event_record_index
= 0;
325 event_record
[event_record_index
].locus
= locus
;
326 event_record
[event_record_index
].type
= type
;
327 event_record_index
++;
334 /* Return the struct x_display_info corresponding to DPY. */
336 struct x_display_info
*
337 x_display_info_for_display (Display
*dpy
)
339 struct x_display_info
*dpyinfo
;
341 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
342 if (dpyinfo
->display
== dpy
)
349 x_find_topmost_parent (struct frame
*f
)
351 struct x_output
*x
= f
->output_data
.x
;
352 Window win
= None
, wi
= x
->parent_desc
;
353 Display
*dpy
= FRAME_X_DISPLAY (f
);
355 while (wi
!= FRAME_DISPLAY_INFO (f
)->root_window
)
359 unsigned int nchildren
;
362 XQueryTree (dpy
, win
, &root
, &wi
, &children
, &nchildren
);
369 #define OPAQUE 0xffffffff
372 x_set_frame_alpha (struct frame
*f
)
374 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
375 Display
*dpy
= FRAME_X_DISPLAY (f
);
376 Window win
= FRAME_OUTER_WINDOW (f
);
378 double alpha_min
= 1.0;
382 if (dpyinfo
->x_highlight_frame
== f
)
387 if (FLOATP (Vframe_alpha_lower_limit
))
388 alpha_min
= XFLOAT_DATA (Vframe_alpha_lower_limit
);
389 else if (INTEGERP (Vframe_alpha_lower_limit
))
390 alpha_min
= (XINT (Vframe_alpha_lower_limit
)) / 100.0;
394 else if (alpha
> 1.0)
396 else if (0.0 <= alpha
&& alpha
< alpha_min
&& alpha_min
<= 1.0)
399 opac
= alpha
* OPAQUE
;
401 x_catch_errors (dpy
);
403 /* If there is a parent from the window manager, put the property there
404 also, to work around broken window managers that fail to do that.
405 Do this unconditionally as this function is called on reparent when
406 alpha has not changed on the frame. */
408 parent
= x_find_topmost_parent (f
);
410 XChangeProperty (dpy
, parent
, dpyinfo
->Xatom_net_wm_window_opacity
,
411 XA_CARDINAL
, 32, PropModeReplace
,
412 (unsigned char *) &opac
, 1L);
414 /* return unless necessary */
419 unsigned long n
, left
;
421 rc
= XGetWindowProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
422 0L, 1L, False
, XA_CARDINAL
,
423 &actual
, &format
, &n
, &left
,
426 if (rc
== Success
&& actual
!= None
)
428 unsigned long value
= *(unsigned long *)data
;
438 XChangeProperty (dpy
, win
, dpyinfo
->Xatom_net_wm_window_opacity
,
439 XA_CARDINAL
, 32, PropModeReplace
,
440 (unsigned char *) &opac
, 1L);
445 x_display_pixel_height (struct x_display_info
*dpyinfo
)
447 return HeightOfScreen (dpyinfo
->screen
);
451 x_display_pixel_width (struct x_display_info
*dpyinfo
)
453 return WidthOfScreen (dpyinfo
->screen
);
457 /***********************************************************************
458 Starting and ending an update
459 ***********************************************************************/
461 /* Start an update of frame F. This function is installed as a hook
462 for update_begin, i.e. it is called when update_begin is called.
463 This function is called prior to calls to x_update_window_begin for
464 each window being updated. Currently, there is nothing to do here
465 because all interesting stuff is done on a window basis. */
468 x_update_begin (struct frame
*f
)
474 /* Start update of window W. */
477 x_update_window_begin (struct window
*w
)
479 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
480 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (f
);
482 w
->output_cursor
= w
->cursor
;
486 if (f
== hlinfo
->mouse_face_mouse_frame
)
488 /* Don't do highlighting for mouse motion during the update. */
489 hlinfo
->mouse_face_defer
= 1;
491 /* If F needs to be redrawn, simply forget about any prior mouse
493 if (FRAME_GARBAGED_P (f
))
494 hlinfo
->mouse_face_window
= Qnil
;
501 /* Draw a vertical window border from (x,y0) to (x,y1) */
504 x_draw_vertical_window_border (struct window
*w
, int x
, int y0
, int y1
)
506 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
509 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
511 XSetForeground (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
514 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
515 f
->output_data
.x
->normal_gc
, x
, y0
, x
, y1
);
518 /* Draw a window divider from (x0,y0) to (x1,y1) */
521 x_draw_window_divider (struct window
*w
, int x0
, int x1
, int y0
, int y1
)
523 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
524 struct face
*face
= FACE_FROM_ID (f
, WINDOW_DIVIDER_FACE_ID
);
525 struct face
*face_first
= FACE_FROM_ID (f
, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID
);
526 struct face
*face_last
= FACE_FROM_ID (f
, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID
);
527 unsigned long color
= face
? face
->foreground
: FRAME_FOREGROUND_PIXEL (f
);
528 unsigned long color_first
= (face_first
529 ? face_first
->foreground
530 : FRAME_FOREGROUND_PIXEL (f
));
531 unsigned long color_last
= (face_last
532 ? face_last
->foreground
533 : FRAME_FOREGROUND_PIXEL (f
));
534 Display
*display
= FRAME_X_DISPLAY (f
);
535 Window window
= FRAME_X_WINDOW (f
);
537 if (y1
- y0
> x1
- x0
&& x1
- x0
> 2)
540 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_first
);
541 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
543 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
544 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
545 x0
+ 1, y0
, x1
- x0
- 2, y1
- y0
);
546 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_last
);
547 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
548 x1
- 1, y0
, 1, y1
- y0
);
550 else if (x1
- x0
> y1
- y0
&& y1
- y0
> 3)
553 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_first
);
554 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
556 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
557 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
558 x0
, y0
+ 1, x1
- x0
, y1
- y0
- 2);
559 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color_last
);
560 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
561 x0
, y1
- 1, x1
- x0
, 1);
565 XSetForeground (display
, f
->output_data
.x
->normal_gc
, color
);
566 XFillRectangle (display
, window
, f
->output_data
.x
->normal_gc
,
567 x0
, y0
, x1
- x0
, y1
- y0
);
571 /* End update of window W.
573 Draw vertical borders between horizontally adjacent windows, and
574 display W's cursor if CURSOR_ON_P is non-zero.
576 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
577 glyphs in mouse-face were overwritten. In that case we have to
578 make sure that the mouse-highlight is properly redrawn.
580 W may be a menu bar pseudo-window in case we don't have X toolkit
581 support. Such windows don't have a cursor, so don't display it
585 x_update_window_end (struct window
*w
, bool cursor_on_p
,
586 bool mouse_face_overwritten_p
)
588 if (!w
->pseudo_window_p
)
593 display_and_set_cursor (w
, 1,
594 w
->output_cursor
.hpos
, w
->output_cursor
.vpos
,
595 w
->output_cursor
.x
, w
->output_cursor
.y
);
597 if (draw_window_fringes (w
, 1))
599 if (WINDOW_RIGHT_DIVIDER_WIDTH (w
))
600 x_draw_right_divider (w
);
602 x_draw_vertical_border (w
);
608 /* If a row with mouse-face was overwritten, arrange for
609 XTframe_up_to_date to redisplay the mouse highlight. */
610 if (mouse_face_overwritten_p
)
612 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (XFRAME (w
->frame
));
614 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
615 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
616 hlinfo
->mouse_face_window
= Qnil
;
621 /* End update of frame F. This function is installed as a hook in
625 x_update_end (struct frame
*f
)
627 /* Mouse highlight may be displayed again. */
628 MOUSE_HL_INFO (f
)->mouse_face_defer
= 0;
632 XFlush (FRAME_X_DISPLAY (f
));
638 /* This function is called from various places in xdisp.c
639 whenever a complete update has been performed. */
642 XTframe_up_to_date (struct frame
*f
)
645 FRAME_MOUSE_UPDATE (f
);
649 /* Clear under internal border if any for non-toolkit builds. */
652 #if !defined USE_X_TOOLKIT && !defined USE_GTK
654 x_clear_under_internal_border (struct frame
*f
)
656 if (FRAME_INTERNAL_BORDER_WIDTH (f
) > 0)
658 Display
*display
= FRAME_X_DISPLAY (f
);
659 Window window
= FRAME_X_WINDOW (f
);
660 int border
= FRAME_INTERNAL_BORDER_WIDTH (f
);
661 int width
= FRAME_PIXEL_WIDTH (f
);
662 int height
= FRAME_PIXEL_HEIGHT (f
);
663 int margin
= FRAME_TOP_MARGIN_HEIGHT (f
);
666 x_clear_area (display
, window
, 0, 0, border
, height
);
667 x_clear_area (display
, window
, 0, margin
, width
, border
);
668 x_clear_area (display
, window
, width
- border
, 0, border
, height
);
669 x_clear_area (display
, window
, 0, height
- border
, width
, border
);
675 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
676 arrow bitmaps, or clear the fringes if no bitmaps are required
677 before DESIRED_ROW is made current. This function is called from
678 update_window_line only if it is known that there are differences
679 between bitmaps to be drawn between current row and DESIRED_ROW. */
682 x_after_update_window_line (struct window
*w
, struct glyph_row
*desired_row
)
686 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
687 desired_row
->redraw_fringe_bitmaps_p
= 1;
690 /* When a window has disappeared, make sure that no rest of
691 full-width rows stays visible in the internal border. Could
692 check here if updated window is the leftmost/rightmost window,
693 but I guess it's not worth doing since vertically split windows
694 are almost never used, internal border is rarely set, and the
695 overhead is very small. */
700 if (windows_or_buffers_changed
701 && desired_row
->full_width_p
702 && (f
= XFRAME (w
->frame
),
703 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
705 && (height
= desired_row
->visible_height
,
708 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
711 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
712 0, y
, width
, height
);
713 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
714 FRAME_PIXEL_WIDTH (f
) - width
,
723 x_draw_fringe_bitmap (struct window
*w
, struct glyph_row
*row
, struct draw_fringe_bitmap_params
*p
)
725 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
726 Display
*display
= FRAME_X_DISPLAY (f
);
727 Window window
= FRAME_X_WINDOW (f
);
728 GC gc
= f
->output_data
.x
->normal_gc
;
729 struct face
*face
= p
->face
;
731 /* Must clip because of partially visible lines. */
732 x_clip_to_row (w
, row
, ANY_AREA
, gc
);
734 if (p
->bx
>= 0 && !p
->overlay_p
)
736 /* In case the same realized face is used for fringes and
737 for something displayed in the text (e.g. face `region' on
738 mono-displays, the fill style may have been changed to
739 FillSolid in x_draw_glyph_string_background. */
741 XSetFillStyle (display
, face
->gc
, FillOpaqueStippled
);
743 XSetForeground (display
, face
->gc
, face
->background
);
745 XFillRectangle (display
, window
, face
->gc
,
746 p
->bx
, p
->by
, p
->nx
, p
->ny
);
749 XSetForeground (display
, face
->gc
, face
->foreground
);
755 Pixmap pixmap
, clipmask
= (Pixmap
) 0;
756 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
760 bits
= (char *) (p
->bits
+ p
->dh
);
762 bits
= (char *) p
->bits
+ p
->dh
;
764 /* Draw the bitmap. I believe these small pixmaps can be cached
766 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, p
->wd
, p
->h
,
768 ? (p
->overlay_p
? face
->background
769 : f
->output_data
.x
->cursor_pixel
)
771 face
->background
, depth
);
775 clipmask
= XCreatePixmapFromBitmapData (display
,
776 FRAME_DISPLAY_INFO (f
)->root_window
,
779 gcv
.clip_mask
= clipmask
;
780 gcv
.clip_x_origin
= p
->x
;
781 gcv
.clip_y_origin
= p
->y
;
782 XChangeGC (display
, gc
, GCClipMask
| GCClipXOrigin
| GCClipYOrigin
, &gcv
);
785 XCopyArea (display
, pixmap
, window
, gc
, 0, 0,
786 p
->wd
, p
->h
, p
->x
, p
->y
);
787 XFreePixmap (display
, pixmap
);
791 gcv
.clip_mask
= (Pixmap
) 0;
792 XChangeGC (display
, gc
, GCClipMask
, &gcv
);
793 XFreePixmap (display
, clipmask
);
797 XSetClipMask (display
, gc
, None
);
800 /***********************************************************************
802 ***********************************************************************/
806 static void x_set_glyph_string_clipping (struct glyph_string
*);
807 static void x_set_glyph_string_gc (struct glyph_string
*);
808 static void x_draw_glyph_string_foreground (struct glyph_string
*);
809 static void x_draw_composite_glyph_string_foreground (struct glyph_string
*);
810 static void x_draw_glyph_string_box (struct glyph_string
*);
811 static void x_draw_glyph_string (struct glyph_string
*);
812 static _Noreturn
void x_delete_glyphs (struct frame
*, int);
813 static void x_compute_glyph_string_overhangs (struct glyph_string
*);
814 static void x_set_cursor_gc (struct glyph_string
*);
815 static void x_set_mode_line_face_gc (struct glyph_string
*);
816 static void x_set_mouse_face_gc (struct glyph_string
*);
817 static bool x_alloc_lighter_color (struct frame
*, Display
*, Colormap
,
818 unsigned long *, double, int);
819 static void x_setup_relief_color (struct frame
*, struct relief
*,
820 double, int, unsigned long);
821 static void x_setup_relief_colors (struct glyph_string
*);
822 static void x_draw_image_glyph_string (struct glyph_string
*);
823 static void x_draw_image_relief (struct glyph_string
*);
824 static void x_draw_image_foreground (struct glyph_string
*);
825 static void x_draw_image_foreground_1 (struct glyph_string
*, Pixmap
);
826 static void x_clear_glyph_string_rect (struct glyph_string
*, int,
828 static void x_draw_relief_rect (struct frame
*, int, int, int, int,
829 int, int, int, int, int, int,
831 static void x_draw_box_rect (struct glyph_string
*, int, int, int, int,
832 int, int, int, XRectangle
*);
833 static void x_scroll_bar_clear (struct frame
*);
836 static void x_check_font (struct frame
*, struct font
*);
840 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
844 x_set_cursor_gc (struct glyph_string
*s
)
846 if (s
->font
== FRAME_FONT (s
->f
)
847 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
848 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
850 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
853 /* Cursor on non-default face: must merge. */
857 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
858 xgcv
.foreground
= s
->face
->background
;
860 /* If the glyph would be invisible, try a different foreground. */
861 if (xgcv
.foreground
== xgcv
.background
)
862 xgcv
.foreground
= s
->face
->foreground
;
863 if (xgcv
.foreground
== xgcv
.background
)
864 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
865 if (xgcv
.foreground
== xgcv
.background
)
866 xgcv
.foreground
= s
->face
->foreground
;
868 /* Make sure the cursor is distinct from text in this face. */
869 if (xgcv
.background
== s
->face
->background
870 && xgcv
.foreground
== s
->face
->foreground
)
872 xgcv
.background
= s
->face
->foreground
;
873 xgcv
.foreground
= s
->face
->background
;
876 IF_DEBUG (x_check_font (s
->f
, s
->font
));
877 xgcv
.graphics_exposures
= False
;
878 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
880 if (FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
881 XChangeGC (s
->display
, FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
884 FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
885 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
887 s
->gc
= FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
892 /* Set up S->gc of glyph string S for drawing text in mouse face. */
895 x_set_mouse_face_gc (struct glyph_string
*s
)
900 /* What face has to be used last for the mouse face? */
901 face_id
= MOUSE_HL_INFO (s
->f
)->mouse_face_face_id
;
902 face
= FACE_FROM_ID (s
->f
, face_id
);
904 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
906 if (s
->first_glyph
->type
== CHAR_GLYPH
)
907 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
909 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
910 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
911 prepare_face_for_display (s
->f
, s
->face
);
913 if (s
->font
== s
->face
->font
)
917 /* Otherwise construct scratch_cursor_gc with values from FACE
922 xgcv
.background
= s
->face
->background
;
923 xgcv
.foreground
= s
->face
->foreground
;
924 xgcv
.graphics_exposures
= False
;
925 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
927 if (FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
928 XChangeGC (s
->display
, FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
931 FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
932 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
934 s
->gc
= FRAME_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
937 eassert (s
->gc
!= 0);
941 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
942 Faces to use in the mode line have already been computed when the
943 matrix was built, so there isn't much to do, here. */
946 x_set_mode_line_face_gc (struct glyph_string
*s
)
952 /* Set S->gc of glyph string S for drawing that glyph string. Set
953 S->stippled_p to a non-zero value if the face of S has a stipple
957 x_set_glyph_string_gc (struct glyph_string
*s
)
959 prepare_face_for_display (s
->f
, s
->face
);
961 if (s
->hl
== DRAW_NORMAL_TEXT
)
964 s
->stippled_p
= s
->face
->stipple
!= 0;
966 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
968 x_set_mode_line_face_gc (s
);
969 s
->stippled_p
= s
->face
->stipple
!= 0;
971 else if (s
->hl
== DRAW_CURSOR
)
976 else if (s
->hl
== DRAW_MOUSE_FACE
)
978 x_set_mouse_face_gc (s
);
979 s
->stippled_p
= s
->face
->stipple
!= 0;
981 else if (s
->hl
== DRAW_IMAGE_RAISED
982 || s
->hl
== DRAW_IMAGE_SUNKEN
)
985 s
->stippled_p
= s
->face
->stipple
!= 0;
990 /* GC must have been set. */
991 eassert (s
->gc
!= 0);
995 /* Set clipping for output of glyph string S. S may be part of a mode
996 line or menu if we don't have X toolkit support. */
999 x_set_glyph_string_clipping (struct glyph_string
*s
)
1001 XRectangle
*r
= s
->clip
;
1002 int n
= get_glyph_string_clip_rects (s
, r
, 2);
1005 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, r
, n
, Unsorted
);
1010 /* Set SRC's clipping for output of glyph string DST. This is called
1011 when we are drawing DST's left_overhang or right_overhang only in
1015 x_set_glyph_string_clipping_exactly (struct glyph_string
*src
, struct glyph_string
*dst
)
1020 r
.width
= src
->width
;
1022 r
.height
= src
->height
;
1025 XSetClipRectangles (dst
->display
, dst
->gc
, 0, 0, &r
, 1, Unsorted
);
1030 Compute left and right overhang of glyph string S. */
1033 x_compute_glyph_string_overhangs (struct glyph_string
*s
)
1036 && (s
->first_glyph
->type
== CHAR_GLYPH
1037 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
1039 struct font_metrics metrics
;
1041 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1043 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1044 struct font
*font
= s
->font
;
1047 for (i
= 0; i
< s
->nchars
; i
++)
1048 code
[i
] = (s
->char2b
[i
].byte1
<< 8) | s
->char2b
[i
].byte2
;
1049 font
->driver
->text_extents (font
, code
, s
->nchars
, &metrics
);
1053 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1055 composition_gstring_width (gstring
, s
->cmp_from
, s
->cmp_to
, &metrics
);
1057 s
->right_overhang
= (metrics
.rbearing
> metrics
.width
1058 ? metrics
.rbearing
- metrics
.width
: 0);
1059 s
->left_overhang
= metrics
.lbearing
< 0 ? - metrics
.lbearing
: 0;
1063 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
1064 s
->left_overhang
= - s
->cmp
->lbearing
;
1069 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1072 x_clear_glyph_string_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
1075 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
1076 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
1077 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
1078 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
1082 /* Draw the background of glyph_string S. If S->background_filled_p
1083 is non-zero don't draw it. FORCE_P non-zero means draw the
1084 background even if it wouldn't be drawn normally. This is used
1085 when a string preceding S draws into the background of S, or S
1086 contains the first component of a composition. */
1089 x_draw_glyph_string_background (struct glyph_string
*s
, bool force_p
)
1091 /* Nothing to do if background has already been drawn or if it
1092 shouldn't be drawn in the first place. */
1093 if (!s
->background_filled_p
)
1095 int box_line_width
= max (s
->face
->box_line_width
, 0);
1099 /* Fill background with a stipple pattern. */
1100 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1101 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1102 s
->y
+ box_line_width
,
1103 s
->background_width
,
1104 s
->height
- 2 * box_line_width
);
1105 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1106 s
->background_filled_p
= 1;
1108 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1109 || s
->font_not_found_p
1110 || s
->extends_to_end_of_line_p
1113 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1114 s
->background_width
,
1115 s
->height
- 2 * box_line_width
);
1116 s
->background_filled_p
= 1;
1122 /* Draw the foreground of glyph string S. */
1125 x_draw_glyph_string_foreground (struct glyph_string
*s
)
1129 /* If first glyph of S has a left box line, start drawing the text
1130 of S to the right of that box line. */
1131 if (s
->face
->box
!= FACE_NO_BOX
1132 && s
->first_glyph
->left_box_line_p
)
1133 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1137 /* Draw characters of S as rectangles if S's font could not be
1139 if (s
->font_not_found_p
)
1141 for (i
= 0; i
< s
->nchars
; ++i
)
1143 struct glyph
*g
= s
->first_glyph
+ i
;
1144 XDrawRectangle (s
->display
, s
->window
,
1145 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1147 x
+= g
->pixel_width
;
1152 struct font
*font
= s
->font
;
1153 int boff
= font
->baseline_offset
;
1156 if (font
->vertical_centering
)
1157 boff
= VCENTER_BASELINE_OFFSET (font
, s
->f
) - boff
;
1159 y
= s
->ybase
- boff
;
1161 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1162 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 0);
1164 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 1);
1165 if (s
->face
->overstrike
)
1166 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, 0);
1170 /* Draw the foreground of composite glyph string S. */
1173 x_draw_composite_glyph_string_foreground (struct glyph_string
*s
)
1176 struct font
*font
= s
->font
;
1178 /* If first glyph of S has a left box line, start drawing the text
1179 of S to the right of that box line. */
1180 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1181 && s
->first_glyph
->left_box_line_p
)
1182 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1186 /* S is a glyph string for a composition. S->cmp_from is the index
1187 of the first character drawn for glyphs of this composition.
1188 S->cmp_from == 0 means we are drawing the very first character of
1189 this composition. */
1191 /* Draw a rectangle for the composition if the font for the very
1192 first character of the composition could not be loaded. */
1193 if (s
->font_not_found_p
)
1195 if (s
->cmp_from
== 0)
1196 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
1197 s
->width
- 1, s
->height
- 1);
1199 else if (! s
->first_glyph
->u
.cmp
.automatic
)
1203 for (i
= 0, j
= s
->cmp_from
; i
< s
->nchars
; i
++, j
++)
1204 /* TAB in a composition means display glyphs with padding
1205 space on the left or right. */
1206 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1208 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1209 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1211 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, 0);
1212 if (s
->face
->overstrike
)
1213 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, 0);
1218 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1223 for (i
= j
= s
->cmp_from
; i
< s
->cmp_to
; i
++)
1225 glyph
= LGSTRING_GLYPH (gstring
, i
);
1226 if (NILP (LGLYPH_ADJUSTMENT (glyph
)))
1227 width
+= LGLYPH_WIDTH (glyph
);
1230 int xoff
, yoff
, wadjust
;
1234 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1235 if (s
->face
->overstrike
)
1236 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, 0);
1239 xoff
= LGLYPH_XOFF (glyph
);
1240 yoff
= LGLYPH_YOFF (glyph
);
1241 wadjust
= LGLYPH_WADJUST (glyph
);
1242 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, 0);
1243 if (s
->face
->overstrike
)
1244 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
+ 1, y
+ yoff
, 0);
1252 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1253 if (s
->face
->overstrike
)
1254 font
->driver
->draw (s
, j
, i
, x
+ 1, y
, 0);
1260 /* Draw the foreground of glyph string S for glyphless characters. */
1263 x_draw_glyphless_glyph_string_foreground (struct glyph_string
*s
)
1265 struct glyph
*glyph
= s
->first_glyph
;
1269 /* If first glyph of S has a left box line, start drawing the text
1270 of S to the right of that box line. */
1271 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1272 && s
->first_glyph
->left_box_line_p
)
1273 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1279 for (i
= 0; i
< s
->nchars
; i
++, glyph
++)
1281 char buf
[7], *str
= NULL
;
1282 int len
= glyph
->u
.glyphless
.len
;
1284 if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_ACRONYM
)
1287 && CHAR_TABLE_P (Vglyphless_char_display
)
1288 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display
))
1292 = (! glyph
->u
.glyphless
.for_no_font
1293 ? CHAR_TABLE_REF (Vglyphless_char_display
,
1294 glyph
->u
.glyphless
.ch
)
1295 : XCHAR_TABLE (Vglyphless_char_display
)->extras
[0]);
1296 if (STRINGP (acronym
))
1297 str
= SSDATA (acronym
);
1300 else if (glyph
->u
.glyphless
.method
== GLYPHLESS_DISPLAY_HEX_CODE
)
1302 sprintf (buf
, "%0*X",
1303 glyph
->u
.glyphless
.ch
< 0x10000 ? 4 : 6,
1304 glyph
->u
.glyphless
.ch
);
1310 int upper_len
= (len
+ 1) / 2;
1313 /* It is assured that all LEN characters in STR is ASCII. */
1314 for (j
= 0; j
< len
; j
++)
1316 code
= s
->font
->driver
->encode_char (s
->font
, str
[j
]);
1317 STORE_XCHAR2B (char2b
+ j
, code
>> 8, code
& 0xFF);
1319 s
->font
->driver
->draw (s
, 0, upper_len
,
1320 x
+ glyph
->slice
.glyphless
.upper_xoff
,
1321 s
->ybase
+ glyph
->slice
.glyphless
.upper_yoff
,
1323 s
->font
->driver
->draw (s
, upper_len
, len
,
1324 x
+ glyph
->slice
.glyphless
.lower_xoff
,
1325 s
->ybase
+ glyph
->slice
.glyphless
.lower_yoff
,
1328 if (glyph
->u
.glyphless
.method
!= GLYPHLESS_DISPLAY_THIN_SPACE
)
1329 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
1330 x
, s
->ybase
- glyph
->ascent
,
1331 glyph
->pixel_width
- 1,
1332 glyph
->ascent
+ glyph
->descent
- 1);
1333 x
+= glyph
->pixel_width
;
1337 #ifdef USE_X_TOOLKIT
1341 /* Return the frame on which widget WIDGET is used.. Abort if frame
1342 cannot be determined. */
1344 static struct frame
*
1345 x_frame_of_widget (Widget widget
)
1347 struct x_display_info
*dpyinfo
;
1348 Lisp_Object tail
, frame
;
1351 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
1353 /* Find the top-level shell of the widget. Note that this function
1354 can be called when the widget is not yet realized, so XtWindow
1355 (widget) == 0. That's the reason we can't simply use
1356 x_any_window_to_frame. */
1357 while (!XtIsTopLevelShell (widget
))
1358 widget
= XtParent (widget
);
1360 /* Look for a frame with that top-level widget. Allocate the color
1361 on that frame to get the right gamma correction value. */
1362 FOR_EACH_FRAME (tail
, frame
)
1366 && f
->output_data
.nothing
!= 1
1367 && FRAME_DISPLAY_INFO (f
) == dpyinfo
1368 && f
->output_data
.x
->widget
== widget
)
1374 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1375 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1376 If this produces the same color as PIXEL, try a color where all RGB
1377 values have DELTA added. Return the allocated color in *PIXEL.
1378 DISPLAY is the X display, CMAP is the colormap to operate on.
1379 Value is true if successful. */
1382 x_alloc_lighter_color_for_widget (Widget widget
, Display
*display
, Colormap cmap
,
1383 unsigned long *pixel
, double factor
, int delta
)
1385 struct frame
*f
= x_frame_of_widget (widget
);
1386 return x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
);
1389 #endif /* USE_LUCID */
1392 /* Structure specifying which arguments should be passed by Xt to
1393 cvt_string_to_pixel. We want the widget's screen and colormap. */
1395 static XtConvertArgRec cvt_string_to_pixel_args
[] =
1397 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.screen
),
1399 {XtWidgetBaseOffset
, (XtPointer
) XtOffset (Widget
, core
.colormap
),
1404 /* The address of this variable is returned by
1405 cvt_string_to_pixel. */
1407 static Pixel cvt_string_to_pixel_value
;
1410 /* Convert a color name to a pixel color.
1412 DPY is the display we are working on.
1414 ARGS is an array of *NARGS XrmValue structures holding additional
1415 information about the widget for which the conversion takes place.
1416 The contents of this array are determined by the specification
1417 in cvt_string_to_pixel_args.
1419 FROM is a pointer to an XrmValue which points to the color name to
1420 convert. TO is an XrmValue in which to return the pixel color.
1422 CLOSURE_RET is a pointer to user-data, in which we record if
1423 we allocated the color or not.
1425 Value is True if successful, False otherwise. */
1428 cvt_string_to_pixel (Display
*dpy
, XrmValue
*args
, Cardinal
*nargs
,
1429 XrmValue
*from
, XrmValue
*to
,
1430 XtPointer
*closure_ret
)
1440 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1441 "wrongParameters", "cvt_string_to_pixel",
1443 "Screen and colormap args required", NULL
, NULL
);
1447 screen
= *(Screen
**) args
[0].addr
;
1448 cmap
= *(Colormap
*) args
[1].addr
;
1449 color_name
= (String
) from
->addr
;
1451 if (strcmp (color_name
, XtDefaultBackground
) == 0)
1453 *closure_ret
= (XtPointer
) False
;
1454 pixel
= WhitePixelOfScreen (screen
);
1456 else if (strcmp (color_name
, XtDefaultForeground
) == 0)
1458 *closure_ret
= (XtPointer
) False
;
1459 pixel
= BlackPixelOfScreen (screen
);
1461 else if (XParseColor (dpy
, cmap
, color_name
, &color
)
1462 && x_alloc_nearest_color_1 (dpy
, cmap
, &color
))
1464 pixel
= color
.pixel
;
1465 *closure_ret
= (XtPointer
) True
;
1470 Cardinal nparams
= 1;
1472 params
[0] = color_name
;
1473 XtAppWarningMsg (XtDisplayToApplicationContext (dpy
),
1474 "badValue", "cvt_string_to_pixel",
1475 "XtToolkitError", "Invalid color `%s'",
1480 if (to
->addr
!= NULL
)
1482 if (to
->size
< sizeof (Pixel
))
1484 to
->size
= sizeof (Pixel
);
1488 *(Pixel
*) to
->addr
= pixel
;
1492 cvt_string_to_pixel_value
= pixel
;
1493 to
->addr
= (XtPointer
) &cvt_string_to_pixel_value
;
1496 to
->size
= sizeof (Pixel
);
1501 /* Free a pixel color which was previously allocated via
1502 cvt_string_to_pixel. This is registered as the destructor
1503 for this type of resource via XtSetTypeConverter.
1505 APP is the application context in which we work.
1507 TO is a pointer to an XrmValue holding the color to free.
1508 CLOSURE is the value we stored in CLOSURE_RET for this color
1509 in cvt_string_to_pixel.
1511 ARGS and NARGS are like for cvt_string_to_pixel. */
1514 cvt_pixel_dtor (XtAppContext app
, XrmValuePtr to
, XtPointer closure
, XrmValuePtr args
,
1519 XtAppWarningMsg (app
, "wrongParameters", "cvt_pixel_dtor",
1521 "Screen and colormap arguments required",
1524 else if (closure
!= NULL
)
1526 /* We did allocate the pixel, so free it. */
1527 Screen
*screen
= *(Screen
**) args
[0].addr
;
1528 Colormap cmap
= *(Colormap
*) args
[1].addr
;
1529 x_free_dpy_colors (DisplayOfScreen (screen
), screen
, cmap
,
1530 (Pixel
*) to
->addr
, 1);
1535 #endif /* USE_X_TOOLKIT */
1538 /* Value is an array of XColor structures for the contents of the
1539 color map of display DPY. Set *NCELLS to the size of the array.
1540 Note that this probably shouldn't be called for large color maps,
1541 say a 24-bit TrueColor map. */
1543 static const XColor
*
1544 x_color_cells (Display
*dpy
, int *ncells
)
1546 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1548 if (dpyinfo
->color_cells
== NULL
)
1550 Screen
*screen
= dpyinfo
->screen
;
1551 int ncolor_cells
= XDisplayCells (dpy
, XScreenNumberOfScreen (screen
));
1554 dpyinfo
->color_cells
= xnmalloc (ncolor_cells
,
1555 sizeof *dpyinfo
->color_cells
);
1556 dpyinfo
->ncolor_cells
= ncolor_cells
;
1558 for (i
= 0; i
< ncolor_cells
; ++i
)
1559 dpyinfo
->color_cells
[i
].pixel
= i
;
1561 XQueryColors (dpy
, dpyinfo
->cmap
,
1562 dpyinfo
->color_cells
, ncolor_cells
);
1565 *ncells
= dpyinfo
->ncolor_cells
;
1566 return dpyinfo
->color_cells
;
1570 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1571 colors in COLORS. Use cached information, if available. */
1574 x_query_colors (struct frame
*f
, XColor
*colors
, int ncolors
)
1576 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
1578 if (dpyinfo
->color_cells
)
1581 for (i
= 0; i
< ncolors
; ++i
)
1583 unsigned long pixel
= colors
[i
].pixel
;
1584 eassert (pixel
< dpyinfo
->ncolor_cells
);
1585 eassert (dpyinfo
->color_cells
[pixel
].pixel
== pixel
);
1586 colors
[i
] = dpyinfo
->color_cells
[pixel
];
1590 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), colors
, ncolors
);
1594 /* On frame F, translate pixel color to RGB values for the color in
1595 COLOR. Use cached information, if available. */
1598 x_query_color (struct frame
*f
, XColor
*color
)
1600 x_query_colors (f
, color
, 1);
1604 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1605 exact match can't be allocated, try the nearest color available.
1606 Value is true if successful. Set *COLOR to the color
1610 x_alloc_nearest_color_1 (Display
*dpy
, Colormap cmap
, XColor
*color
)
1614 rc
= XAllocColor (dpy
, cmap
, color
) != 0;
1617 /* If we got to this point, the colormap is full, so we're going
1618 to try to get the next closest color. The algorithm used is
1619 a least-squares matching, which is what X uses for closest
1620 color matching with StaticColor visuals. */
1622 int max_color_delta
= 255;
1623 int max_delta
= 3 * max_color_delta
;
1624 int nearest_delta
= max_delta
+ 1;
1626 const XColor
*cells
= x_color_cells (dpy
, &ncells
);
1628 for (nearest
= i
= 0; i
< ncells
; ++i
)
1630 int dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
1631 int dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
1632 int dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
1633 int delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
1635 if (delta
< nearest_delta
)
1638 nearest_delta
= delta
;
1642 color
->red
= cells
[nearest
].red
;
1643 color
->green
= cells
[nearest
].green
;
1644 color
->blue
= cells
[nearest
].blue
;
1645 rc
= XAllocColor (dpy
, cmap
, color
) != 0;
1649 /* If allocation succeeded, and the allocated pixel color is not
1650 equal to a cached pixel color recorded earlier, there was a
1651 change in the colormap, so clear the color cache. */
1652 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
1653 XColor
*cached_color
;
1655 if (dpyinfo
->color_cells
1656 && (cached_color
= &dpyinfo
->color_cells
[color
->pixel
],
1657 (cached_color
->red
!= color
->red
1658 || cached_color
->blue
!= color
->blue
1659 || cached_color
->green
!= color
->green
)))
1661 xfree (dpyinfo
->color_cells
);
1662 dpyinfo
->color_cells
= NULL
;
1663 dpyinfo
->ncolor_cells
= 0;
1667 #ifdef DEBUG_X_COLORS
1669 register_color (color
->pixel
);
1670 #endif /* DEBUG_X_COLORS */
1676 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1677 exact match can't be allocated, try the nearest color available.
1678 Value is true if successful. Set *COLOR to the color
1682 x_alloc_nearest_color (struct frame
*f
, Colormap cmap
, XColor
*color
)
1684 gamma_correct (f
, color
);
1685 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f
), cmap
, color
);
1689 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1690 It's necessary to do this instead of just using PIXEL directly to
1691 get color reference counts right. */
1694 x_copy_color (struct frame
*f
, unsigned long pixel
)
1698 color
.pixel
= pixel
;
1700 x_query_color (f
, &color
);
1701 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
1703 #ifdef DEBUG_X_COLORS
1704 register_color (pixel
);
1710 /* Brightness beyond which a color won't have its highlight brightness
1713 Nominally, highlight colors for `3d' faces are calculated by
1714 brightening an object's color by a constant scale factor, but this
1715 doesn't yield good results for dark colors, so for colors who's
1716 brightness is less than this value (on a scale of 0-65535) have an
1717 use an additional additive factor.
1719 The value here is set so that the default menu-bar/mode-line color
1720 (grey75) will not have its highlights changed at all. */
1721 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1724 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1725 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1726 If this produces the same color as PIXEL, try a color where all RGB
1727 values have DELTA added. Return the allocated color in *PIXEL.
1728 DISPLAY is the X display, CMAP is the colormap to operate on.
1729 Value is non-zero if successful. */
1732 x_alloc_lighter_color (struct frame
*f
, Display
*display
, Colormap cmap
,
1733 unsigned long *pixel
, double factor
, int delta
)
1739 /* Get RGB color values. */
1740 color
.pixel
= *pixel
;
1741 x_query_color (f
, &color
);
1743 /* Change RGB values by specified FACTOR. Avoid overflow! */
1744 eassert (factor
>= 0);
1745 new.red
= min (0xffff, factor
* color
.red
);
1746 new.green
= min (0xffff, factor
* color
.green
);
1747 new.blue
= min (0xffff, factor
* color
.blue
);
1749 /* Calculate brightness of COLOR. */
1750 bright
= (2 * color
.red
+ 3 * color
.green
+ color
.blue
) / 6;
1752 /* We only boost colors that are darker than
1753 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1754 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1755 /* Make an additive adjustment to NEW, because it's dark enough so
1756 that scaling by FACTOR alone isn't enough. */
1758 /* How far below the limit this color is (0 - 1, 1 being darker). */
1759 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1760 /* The additive adjustment. */
1761 int min_delta
= delta
* dimness
* factor
/ 2;
1765 new.red
= max (0, new.red
- min_delta
);
1766 new.green
= max (0, new.green
- min_delta
);
1767 new.blue
= max (0, new.blue
- min_delta
);
1771 new.red
= min (0xffff, min_delta
+ new.red
);
1772 new.green
= min (0xffff, min_delta
+ new.green
);
1773 new.blue
= min (0xffff, min_delta
+ new.blue
);
1777 /* Try to allocate the color. */
1778 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1781 if (new.pixel
== *pixel
)
1783 /* If we end up with the same color as before, try adding
1784 delta to the RGB values. */
1785 x_free_colors (f
, &new.pixel
, 1);
1787 new.red
= min (0xffff, delta
+ color
.red
);
1788 new.green
= min (0xffff, delta
+ color
.green
);
1789 new.blue
= min (0xffff, delta
+ color
.blue
);
1790 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
1801 /* Set up the foreground color for drawing relief lines of glyph
1802 string S. RELIEF is a pointer to a struct relief containing the GC
1803 with which lines will be drawn. Use a color that is FACTOR or
1804 DELTA lighter or darker than the relief's background which is found
1805 in S->f->output_data.x->relief_background. If such a color cannot
1806 be allocated, use DEFAULT_PIXEL, instead. */
1809 x_setup_relief_color (struct frame
*f
, struct relief
*relief
, double factor
,
1810 int delta
, unsigned long default_pixel
)
1813 struct x_output
*di
= f
->output_data
.x
;
1814 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
1815 unsigned long pixel
;
1816 unsigned long background
= di
->relief_background
;
1817 Colormap cmap
= FRAME_X_COLORMAP (f
);
1818 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
1819 Display
*dpy
= FRAME_X_DISPLAY (f
);
1821 xgcv
.graphics_exposures
= False
;
1822 xgcv
.line_width
= 1;
1824 /* Free previously allocated color. The color cell will be reused
1825 when it has been freed as many times as it was allocated, so this
1826 doesn't affect faces using the same colors. */
1827 if (relief
->gc
&& relief
->pixel
!= -1)
1829 x_free_colors (f
, &relief
->pixel
, 1);
1833 /* Allocate new color. */
1834 xgcv
.foreground
= default_pixel
;
1836 if (dpyinfo
->n_planes
!= 1
1837 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
1838 xgcv
.foreground
= relief
->pixel
= pixel
;
1840 if (relief
->gc
== 0)
1842 xgcv
.stipple
= dpyinfo
->gray
;
1844 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
1847 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
1851 /* Set up colors for the relief lines around glyph string S. */
1854 x_setup_relief_colors (struct glyph_string
*s
)
1856 struct x_output
*di
= s
->f
->output_data
.x
;
1857 unsigned long color
;
1859 if (s
->face
->use_box_color_for_shadows_p
)
1860 color
= s
->face
->box_color
;
1861 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1863 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1864 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1869 /* Get the background color of the face. */
1870 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
1871 color
= xgcv
.background
;
1874 if (di
->white_relief
.gc
== 0
1875 || color
!= di
->relief_background
)
1877 di
->relief_background
= color
;
1878 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1879 WHITE_PIX_DEFAULT (s
->f
));
1880 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1881 BLACK_PIX_DEFAULT (s
->f
));
1886 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1887 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1888 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1889 relief. LEFT_P non-zero means draw a relief on the left side of
1890 the rectangle. RIGHT_P non-zero means draw a relief on the right
1891 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1895 x_draw_relief_rect (struct frame
*f
,
1896 int left_x
, int top_y
, int right_x
, int bottom_y
, int width
,
1897 int raised_p
, int top_p
, int bot_p
, int left_p
, int right_p
,
1898 XRectangle
*clip_rect
)
1900 Display
*dpy
= FRAME_X_DISPLAY (f
);
1901 Window window
= FRAME_X_WINDOW (f
);
1906 gc
= f
->output_data
.x
->white_relief
.gc
;
1908 gc
= f
->output_data
.x
->black_relief
.gc
;
1909 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
1911 /* This code is more complicated than it has to be, because of two
1912 minor hacks to make the boxes look nicer: (i) if width > 1, draw
1913 the outermost line using the black relief. (ii) Omit the four
1920 XDrawLine (dpy
, window
, gc
,
1921 left_x
+ (left_p
? 1 : 0), top_y
,
1922 right_x
+ (right_p
? 0 : 1), top_y
);
1924 for (i
= 1; i
< width
; ++i
)
1925 XDrawLine (dpy
, window
, gc
,
1926 left_x
+ i
* left_p
, top_y
+ i
,
1927 right_x
+ 1 - i
* right_p
, top_y
+ i
);
1934 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
1936 XClearArea (dpy
, window
, left_x
, top_y
, 1, 1, False
);
1937 XClearArea (dpy
, window
, left_x
, bottom_y
, 1, 1, False
);
1939 for (i
= (width
> 1 ? 1 : 0); i
< width
; ++i
)
1940 XDrawLine (dpy
, window
, gc
,
1941 left_x
+ i
, top_y
+ (i
+ 1) * top_p
,
1942 left_x
+ i
, bottom_y
+ 1 - (i
+ 1) * bot_p
);
1945 XSetClipMask (dpy
, gc
, None
);
1947 gc
= f
->output_data
.x
->black_relief
.gc
;
1949 gc
= f
->output_data
.x
->white_relief
.gc
;
1950 XSetClipRectangles (dpy
, gc
, 0, 0, clip_rect
, 1, Unsorted
);
1954 /* Outermost top line. */
1956 XDrawLine (dpy
, window
, gc
,
1957 left_x
+ (left_p
? 1 : 0), top_y
,
1958 right_x
+ (right_p
? 0 : 1), top_y
);
1960 /* Outermost left line. */
1962 XDrawLine (dpy
, window
, gc
, left_x
, top_y
+ 1, left_x
, bottom_y
);
1968 XDrawLine (dpy
, window
, gc
,
1969 left_x
+ (left_p
? 1 : 0), bottom_y
,
1970 right_x
+ (right_p
? 0 : 1), bottom_y
);
1971 for (i
= 1; i
< width
; ++i
)
1972 XDrawLine (dpy
, window
, gc
,
1973 left_x
+ i
* left_p
, bottom_y
- i
,
1974 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
1980 XClearArea (dpy
, window
, right_x
, top_y
, 1, 1, False
);
1981 XClearArea (dpy
, window
, right_x
, bottom_y
, 1, 1, False
);
1982 for (i
= 0; i
< width
; ++i
)
1983 XDrawLine (dpy
, window
, gc
,
1984 right_x
- i
, top_y
+ (i
+ 1) * top_p
,
1985 right_x
- i
, bottom_y
+ 1 - (i
+ 1) * bot_p
);
1988 XSetClipMask (dpy
, gc
, None
);
1992 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1993 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1994 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1995 left side of the rectangle. RIGHT_P non-zero means draw a line
1996 on the right side of the rectangle. CLIP_RECT is the clipping
1997 rectangle to use when drawing. */
2000 x_draw_box_rect (struct glyph_string
*s
,
2001 int left_x
, int top_y
, int right_x
, int bottom_y
, int width
,
2002 int left_p
, int right_p
, XRectangle
*clip_rect
)
2006 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2007 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2008 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
2011 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2012 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2016 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2017 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2020 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2021 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2025 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2026 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2028 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2029 XSetClipMask (s
->display
, s
->gc
, None
);
2033 /* Draw a box around glyph string S. */
2036 x_draw_glyph_string_box (struct glyph_string
*s
)
2038 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2039 int left_p
, right_p
;
2040 struct glyph
*last_glyph
;
2041 XRectangle clip_rect
;
2043 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2044 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2045 : window_box_right (s
->w
, s
->area
));
2047 /* The glyph that may have a right box line. */
2048 last_glyph
= (s
->cmp
|| s
->img
2050 : s
->first_glyph
+ s
->nchars
- 1);
2052 width
= eabs (s
->face
->box_line_width
);
2053 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2055 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2057 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2059 bottom_y
= top_y
+ s
->height
- 1;
2061 left_p
= (s
->first_glyph
->left_box_line_p
2062 || (s
->hl
== DRAW_MOUSE_FACE
2064 || s
->prev
->hl
!= s
->hl
)));
2065 right_p
= (last_glyph
->right_box_line_p
2066 || (s
->hl
== DRAW_MOUSE_FACE
2068 || s
->next
->hl
!= s
->hl
)));
2070 get_glyph_string_clip_rect (s
, &clip_rect
);
2072 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2073 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2074 left_p
, right_p
, &clip_rect
);
2077 x_setup_relief_colors (s
);
2078 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2079 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2084 /* Draw foreground of image glyph string S. */
2087 x_draw_image_foreground (struct glyph_string
*s
)
2090 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2092 /* If first glyph of S has a left box line, start drawing it to the
2093 right of that line. */
2094 if (s
->face
->box
!= FACE_NO_BOX
2095 && s
->first_glyph
->left_box_line_p
2097 x
+= eabs (s
->face
->box_line_width
);
2099 /* If there is a margin around the image, adjust x- and y-position
2101 if (s
->slice
.x
== 0)
2102 x
+= s
->img
->hmargin
;
2103 if (s
->slice
.y
== 0)
2104 y
+= s
->img
->vmargin
;
2110 /* We can't set both a clip mask and use XSetClipRectangles
2111 because the latter also sets a clip mask. We also can't
2112 trust on the shape extension to be available
2113 (XShapeCombineRegion). So, compute the rectangle to draw
2115 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2118 XRectangle clip_rect
, image_rect
, r
;
2120 xgcv
.clip_mask
= s
->img
->mask
;
2121 xgcv
.clip_x_origin
= x
;
2122 xgcv
.clip_y_origin
= y
;
2123 xgcv
.function
= GXcopy
;
2124 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2126 get_glyph_string_clip_rect (s
, &clip_rect
);
2129 image_rect
.width
= s
->slice
.width
;
2130 image_rect
.height
= s
->slice
.height
;
2131 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2132 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2133 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2134 r
.width
, r
.height
, r
.x
, r
.y
);
2138 XRectangle clip_rect
, image_rect
, r
;
2140 get_glyph_string_clip_rect (s
, &clip_rect
);
2143 image_rect
.width
= s
->slice
.width
;
2144 image_rect
.height
= s
->slice
.height
;
2145 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2146 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2147 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2148 r
.width
, r
.height
, r
.x
, r
.y
);
2150 /* When the image has a mask, we can expect that at
2151 least part of a mouse highlight or a block cursor will
2152 be visible. If the image doesn't have a mask, make
2153 a block cursor visible by drawing a rectangle around
2154 the image. I believe it's looking better if we do
2155 nothing here for mouse-face. */
2156 if (s
->hl
== DRAW_CURSOR
)
2158 int relief
= eabs (s
->img
->relief
);
2159 XDrawRectangle (s
->display
, s
->window
, s
->gc
,
2160 x
- relief
, y
- relief
,
2161 s
->slice
.width
+ relief
*2 - 1,
2162 s
->slice
.height
+ relief
*2 - 1);
2167 /* Draw a rectangle if image could not be loaded. */
2168 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2169 s
->slice
.width
- 1, s
->slice
.height
- 1);
2173 /* Draw a relief around the image glyph string S. */
2176 x_draw_image_relief (struct glyph_string
*s
)
2178 int x1
, y1
, thick
, raised_p
, top_p
, bot_p
, left_p
, right_p
;
2179 int extra_x
, extra_y
;
2182 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2184 /* If first glyph of S has a left box line, start drawing it to the
2185 right of that line. */
2186 if (s
->face
->box
!= FACE_NO_BOX
2187 && s
->first_glyph
->left_box_line_p
2189 x
+= eabs (s
->face
->box_line_width
);
2191 /* If there is a margin around the image, adjust x- and y-position
2193 if (s
->slice
.x
== 0)
2194 x
+= s
->img
->hmargin
;
2195 if (s
->slice
.y
== 0)
2196 y
+= s
->img
->vmargin
;
2198 if (s
->hl
== DRAW_IMAGE_SUNKEN
2199 || s
->hl
== DRAW_IMAGE_RAISED
)
2201 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2202 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2206 thick
= eabs (s
->img
->relief
);
2207 raised_p
= s
->img
->relief
> 0;
2210 x1
= x
+ s
->slice
.width
- 1;
2211 y1
= y
+ s
->slice
.height
- 1;
2213 extra_x
= extra_y
= 0;
2214 if (s
->face
->id
== TOOL_BAR_FACE_ID
)
2216 if (CONSP (Vtool_bar_button_margin
)
2217 && INTEGERP (XCAR (Vtool_bar_button_margin
))
2218 && INTEGERP (XCDR (Vtool_bar_button_margin
)))
2220 extra_x
= XINT (XCAR (Vtool_bar_button_margin
));
2221 extra_y
= XINT (XCDR (Vtool_bar_button_margin
));
2223 else if (INTEGERP (Vtool_bar_button_margin
))
2224 extra_x
= extra_y
= XINT (Vtool_bar_button_margin
);
2227 top_p
= bot_p
= left_p
= right_p
= 0;
2229 if (s
->slice
.x
== 0)
2230 x
-= thick
+ extra_x
, left_p
= 1;
2231 if (s
->slice
.y
== 0)
2232 y
-= thick
+ extra_y
, top_p
= 1;
2233 if (s
->slice
.x
+ s
->slice
.width
== s
->img
->width
)
2234 x1
+= thick
+ extra_x
, right_p
= 1;
2235 if (s
->slice
.y
+ s
->slice
.height
== s
->img
->height
)
2236 y1
+= thick
+ extra_y
, bot_p
= 1;
2238 x_setup_relief_colors (s
);
2239 get_glyph_string_clip_rect (s
, &r
);
2240 x_draw_relief_rect (s
->f
, x
, y
, x1
, y1
, thick
, raised_p
,
2241 top_p
, bot_p
, left_p
, right_p
, &r
);
2245 /* Draw the foreground of image glyph string S to PIXMAP. */
2248 x_draw_image_foreground_1 (struct glyph_string
*s
, Pixmap pixmap
)
2251 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2253 /* If first glyph of S has a left box line, start drawing it to the
2254 right of that line. */
2255 if (s
->face
->box
!= FACE_NO_BOX
2256 && s
->first_glyph
->left_box_line_p
2258 x
+= eabs (s
->face
->box_line_width
);
2260 /* If there is a margin around the image, adjust x- and y-position
2262 if (s
->slice
.x
== 0)
2263 x
+= s
->img
->hmargin
;
2264 if (s
->slice
.y
== 0)
2265 y
+= s
->img
->vmargin
;
2271 /* We can't set both a clip mask and use XSetClipRectangles
2272 because the latter also sets a clip mask. We also can't
2273 trust on the shape extension to be available
2274 (XShapeCombineRegion). So, compute the rectangle to draw
2276 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
2280 xgcv
.clip_mask
= s
->img
->mask
;
2281 xgcv
.clip_x_origin
= x
- s
->slice
.x
;
2282 xgcv
.clip_y_origin
= y
- s
->slice
.y
;
2283 xgcv
.function
= GXcopy
;
2284 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
2286 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2287 s
->slice
.x
, s
->slice
.y
,
2288 s
->slice
.width
, s
->slice
.height
, x
, y
);
2289 XSetClipMask (s
->display
, s
->gc
, None
);
2293 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2294 s
->slice
.x
, s
->slice
.y
,
2295 s
->slice
.width
, s
->slice
.height
, x
, y
);
2297 /* When the image has a mask, we can expect that at
2298 least part of a mouse highlight or a block cursor will
2299 be visible. If the image doesn't have a mask, make
2300 a block cursor visible by drawing a rectangle around
2301 the image. I believe it's looking better if we do
2302 nothing here for mouse-face. */
2303 if (s
->hl
== DRAW_CURSOR
)
2305 int r
= eabs (s
->img
->relief
);
2306 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2307 s
->slice
.width
+ r
*2 - 1,
2308 s
->slice
.height
+ r
*2 - 1);
2313 /* Draw a rectangle if image could not be loaded. */
2314 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
2315 s
->slice
.width
- 1, s
->slice
.height
- 1);
2319 /* Draw part of the background of glyph string S. X, Y, W, and H
2320 give the rectangle to draw. */
2323 x_draw_glyph_string_bg_rect (struct glyph_string
*s
, int x
, int y
, int w
, int h
)
2327 /* Fill background with a stipple pattern. */
2328 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2329 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2330 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2333 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2337 /* Draw image glyph string S.
2340 s->x +-------------------------
2343 | +-------------------------
2346 | | +-------------------
2352 x_draw_image_glyph_string (struct glyph_string
*s
)
2354 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
2355 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2357 Pixmap pixmap
= None
;
2360 if (s
->slice
.y
== 0)
2361 height
-= box_line_vwidth
;
2362 if (s
->slice
.y
+ s
->slice
.height
>= s
->img
->height
)
2363 height
-= box_line_vwidth
;
2365 /* Fill background with face under the image. Do it only if row is
2366 taller than image or if image has a clip mask to reduce
2368 s
->stippled_p
= s
->face
->stipple
!= 0;
2369 if (height
> s
->slice
.height
2373 || s
->img
->pixmap
== 0
2374 || s
->width
!= s
->background_width
)
2378 /* Create a pixmap as large as the glyph string. Fill it
2379 with the background color. Copy the image to it, using
2380 its mask. Copy the temporary pixmap to the display. */
2381 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2382 int depth
= DefaultDepthOfScreen (screen
);
2384 /* Create a pixmap as large as the glyph string. */
2385 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2386 s
->background_width
,
2389 /* Don't clip in the following because we're working on the
2391 XSetClipMask (s
->display
, s
->gc
, None
);
2393 /* Fill the pixmap with the background color/stipple. */
2396 /* Fill background with a stipple pattern. */
2397 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2398 XSetTSOrigin (s
->display
, s
->gc
, - s
->x
, - s
->y
);
2399 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2400 0, 0, s
->background_width
, s
->height
);
2401 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2402 XSetTSOrigin (s
->display
, s
->gc
, 0, 0);
2407 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2409 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2410 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2411 0, 0, s
->background_width
, s
->height
);
2412 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2419 int width
= s
->background_width
;
2421 if (s
->first_glyph
->left_box_line_p
2424 x
+= box_line_hwidth
;
2425 width
-= box_line_hwidth
;
2428 if (s
->slice
.y
== 0)
2429 y
+= box_line_vwidth
;
2431 x_draw_glyph_string_bg_rect (s
, x
, y
, width
, height
);
2434 s
->background_filled_p
= 1;
2437 /* Draw the foreground. */
2440 x_draw_image_foreground_1 (s
, pixmap
);
2441 x_set_glyph_string_clipping (s
);
2442 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
2443 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2444 XFreePixmap (s
->display
, pixmap
);
2447 x_draw_image_foreground (s
);
2449 /* If we must draw a relief around the image, do it. */
2451 || s
->hl
== DRAW_IMAGE_RAISED
2452 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2453 x_draw_image_relief (s
);
2457 /* Draw stretch glyph string S. */
2460 x_draw_stretch_glyph_string (struct glyph_string
*s
)
2462 eassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2464 if (s
->hl
== DRAW_CURSOR
2465 && !x_stretch_cursor_p
)
2467 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2468 wide as the stretch glyph. */
2469 int width
, background_width
= s
->background_width
;
2472 if (!s
->row
->reversed_p
)
2474 int left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2478 background_width
-= left_x
- x
;
2484 /* In R2L rows, draw the cursor on the right edge of the
2486 int right_x
= window_box_right_offset (s
->w
, TEXT_AREA
);
2488 if (x
+ background_width
> right_x
)
2489 background_width
-= x
- right_x
;
2490 x
+= background_width
;
2492 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
2493 if (s
->row
->reversed_p
)
2497 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
2499 /* Clear rest using the GC of the original non-cursor face. */
2500 if (width
< background_width
)
2503 int w
= background_width
- width
, h
= s
->height
;
2507 if (!s
->row
->reversed_p
)
2511 if (s
->row
->mouse_face_p
2512 && cursor_in_mouse_face_p (s
->w
))
2514 x_set_mouse_face_gc (s
);
2520 get_glyph_string_clip_rect (s
, &r
);
2521 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
2523 if (s
->face
->stipple
)
2525 /* Fill background with a stipple pattern. */
2526 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2527 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2528 XSetFillStyle (s
->display
, gc
, FillSolid
);
2533 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2534 XSetForeground (s
->display
, gc
, xgcv
.background
);
2535 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2536 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2539 XSetClipMask (s
->display
, gc
, None
);
2542 else if (!s
->background_filled_p
)
2544 int background_width
= s
->background_width
;
2545 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2547 /* Don't draw into left margin, fringe or scrollbar area
2548 except for header line and mode line. */
2549 if (x
< left_x
&& !s
->row
->mode_line_p
)
2551 background_width
-= left_x
- x
;
2554 if (background_width
> 0)
2555 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
2558 s
->background_filled_p
= 1;
2562 Draw a wavy line under S. The wave fills wave_height pixels from y0.
2568 wave_height = 3 | * * * *
2573 x_draw_underwave (struct glyph_string
*s
)
2575 int wave_height
= 3, wave_length
= 2;
2576 int dx
, dy
, x0
, y0
, width
, x1
, y1
, x2
, y2
, odd
, xmax
;
2577 XRectangle wave_clip
, string_clip
, final_clip
;
2580 dy
= wave_height
- 1;
2582 y0
= s
->ybase
- wave_height
+ 3;
2586 /* Find and set clipping rectangle */
2590 wave_clip
.width
= width
;
2591 wave_clip
.height
= wave_height
;
2592 get_glyph_string_clip_rect (s
, &string_clip
);
2594 if (!x_intersect_rectangles (&wave_clip
, &string_clip
, &final_clip
))
2597 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &final_clip
, 1, Unsorted
);
2599 /* Draw the waves */
2601 x1
= x0
- (x0
% dx
);
2611 if (INT_MAX
- dx
< xmax
)
2616 XDrawLine (s
->display
, s
->window
, s
->gc
, x1
, y1
, x2
, y2
);
2618 x2
+= dx
, y2
= y0
+ odd
*dy
;
2622 /* Restore previous clipping rectangle(s) */
2623 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, s
->clip
, s
->num_clips
, Unsorted
);
2627 /* Draw glyph string S. */
2630 x_draw_glyph_string (struct glyph_string
*s
)
2632 bool relief_drawn_p
= 0;
2634 /* If S draws into the background of its successors, draw the
2635 background of the successors first so that S can draw into it.
2636 This makes S->next use XDrawString instead of XDrawImageString. */
2637 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
2640 struct glyph_string
*next
;
2642 for (width
= 0, next
= s
->next
;
2643 next
&& width
< s
->right_overhang
;
2644 width
+= next
->width
, next
= next
->next
)
2645 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
2647 x_set_glyph_string_gc (next
);
2648 x_set_glyph_string_clipping (next
);
2649 if (next
->first_glyph
->type
== STRETCH_GLYPH
)
2650 x_draw_stretch_glyph_string (next
);
2652 x_draw_glyph_string_background (next
, 1);
2653 next
->num_clips
= 0;
2657 /* Set up S->gc, set clipping and draw S. */
2658 x_set_glyph_string_gc (s
);
2660 /* Draw relief (if any) in advance for char/composition so that the
2661 glyph string can be drawn over it. */
2662 if (!s
->for_overlaps
2663 && s
->face
->box
!= FACE_NO_BOX
2664 && (s
->first_glyph
->type
== CHAR_GLYPH
2665 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2668 x_set_glyph_string_clipping (s
);
2669 x_draw_glyph_string_background (s
, 1);
2670 x_draw_glyph_string_box (s
);
2671 x_set_glyph_string_clipping (s
);
2674 else if (!s
->clip_head
/* draw_glyphs didn't specify a clip mask. */
2676 && ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
2677 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
)))
2678 /* We must clip just this glyph. left_overhang part has already
2679 drawn when s->prev was drawn, and right_overhang part will be
2680 drawn later when s->next is drawn. */
2681 x_set_glyph_string_clipping_exactly (s
, s
);
2683 x_set_glyph_string_clipping (s
);
2685 switch (s
->first_glyph
->type
)
2688 x_draw_image_glyph_string (s
);
2692 x_draw_stretch_glyph_string (s
);
2696 if (s
->for_overlaps
)
2697 s
->background_filled_p
= 1;
2699 x_draw_glyph_string_background (s
, 0);
2700 x_draw_glyph_string_foreground (s
);
2703 case COMPOSITE_GLYPH
:
2704 if (s
->for_overlaps
|| (s
->cmp_from
> 0
2705 && ! s
->first_glyph
->u
.cmp
.automatic
))
2706 s
->background_filled_p
= 1;
2708 x_draw_glyph_string_background (s
, 1);
2709 x_draw_composite_glyph_string_foreground (s
);
2712 case GLYPHLESS_GLYPH
:
2713 if (s
->for_overlaps
)
2714 s
->background_filled_p
= 1;
2716 x_draw_glyph_string_background (s
, 1);
2717 x_draw_glyphless_glyph_string_foreground (s
);
2724 if (!s
->for_overlaps
)
2726 /* Draw underline. */
2727 if (s
->face
->underline_p
)
2729 if (s
->face
->underline_type
== FACE_UNDER_WAVE
)
2731 if (s
->face
->underline_defaulted_p
)
2732 x_draw_underwave (s
);
2736 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2737 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2738 x_draw_underwave (s
);
2739 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2742 else if (s
->face
->underline_type
== FACE_UNDER_LINE
)
2744 unsigned long thickness
, position
;
2747 if (s
->prev
&& s
->prev
->face
->underline_p
2748 && s
->prev
->face
->underline_type
== FACE_UNDER_LINE
)
2750 /* We use the same underline style as the previous one. */
2751 thickness
= s
->prev
->underline_thickness
;
2752 position
= s
->prev
->underline_position
;
2756 /* Get the underline thickness. Default is 1 pixel. */
2757 if (s
->font
&& s
->font
->underline_thickness
> 0)
2758 thickness
= s
->font
->underline_thickness
;
2761 if (x_underline_at_descent_line
)
2762 position
= (s
->height
- thickness
) - (s
->ybase
- s
->y
);
2765 /* Get the underline position. This is the recommended
2766 vertical offset in pixels from the baseline to the top of
2767 the underline. This is a signed value according to the
2768 specs, and its default is
2770 ROUND ((maximum descent) / 2), with
2771 ROUND(x) = floor (x + 0.5) */
2773 if (x_use_underline_position_properties
2774 && s
->font
&& s
->font
->underline_position
>= 0)
2775 position
= s
->font
->underline_position
;
2777 position
= (s
->font
->descent
+ 1) / 2;
2779 position
= underline_minimum_offset
;
2781 position
= max (position
, underline_minimum_offset
);
2783 /* Check the sanity of thickness and position. We should
2784 avoid drawing underline out of the current line area. */
2785 if (s
->y
+ s
->height
<= s
->ybase
+ position
)
2786 position
= (s
->height
- 1) - (s
->ybase
- s
->y
);
2787 if (s
->y
+ s
->height
< s
->ybase
+ position
+ thickness
)
2788 thickness
= (s
->y
+ s
->height
) - (s
->ybase
+ position
);
2789 s
->underline_thickness
= thickness
;
2790 s
->underline_position
= position
;
2791 y
= s
->ybase
+ position
;
2792 if (s
->face
->underline_defaulted_p
)
2793 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2794 s
->x
, y
, s
->width
, thickness
);
2798 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2799 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
2800 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2801 s
->x
, y
, s
->width
, thickness
);
2802 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2806 /* Draw overline. */
2807 if (s
->face
->overline_p
)
2809 unsigned long dy
= 0, h
= 1;
2811 if (s
->face
->overline_color_defaulted_p
)
2812 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2817 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2818 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
2819 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2821 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2825 /* Draw strike-through. */
2826 if (s
->face
->strike_through_p
)
2828 unsigned long h
= 1;
2829 unsigned long dy
= (s
->height
- h
) / 2;
2831 if (s
->face
->strike_through_color_defaulted_p
)
2832 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2837 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2838 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
2839 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
2841 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2845 /* Draw relief if not yet drawn. */
2846 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2847 x_draw_glyph_string_box (s
);
2851 struct glyph_string
*prev
;
2853 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
2854 if (prev
->hl
!= s
->hl
2855 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
2857 /* As prev was drawn while clipped to its own area, we
2858 must draw the right_overhang part using s->hl now. */
2859 enum draw_glyphs_face save
= prev
->hl
;
2862 x_set_glyph_string_gc (prev
);
2863 x_set_glyph_string_clipping_exactly (s
, prev
);
2864 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
2865 x_draw_glyph_string_foreground (prev
);
2867 x_draw_composite_glyph_string_foreground (prev
);
2868 XSetClipMask (prev
->display
, prev
->gc
, None
);
2870 prev
->num_clips
= 0;
2876 struct glyph_string
*next
;
2878 for (next
= s
->next
; next
; next
= next
->next
)
2879 if (next
->hl
!= s
->hl
2880 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
2882 /* As next will be drawn while clipped to its own area,
2883 we must draw the left_overhang part using s->hl now. */
2884 enum draw_glyphs_face save
= next
->hl
;
2887 x_set_glyph_string_gc (next
);
2888 x_set_glyph_string_clipping_exactly (s
, next
);
2889 if (next
->first_glyph
->type
== CHAR_GLYPH
)
2890 x_draw_glyph_string_foreground (next
);
2892 x_draw_composite_glyph_string_foreground (next
);
2893 XSetClipMask (next
->display
, next
->gc
, None
);
2895 next
->num_clips
= 0;
2896 next
->clip_head
= s
->next
;
2901 /* Reset clipping. */
2902 XSetClipMask (s
->display
, s
->gc
, None
);
2906 /* Shift display to make room for inserted glyphs. */
2909 x_shift_glyphs_for_insert (struct frame
*f
, int x
, int y
, int width
, int height
, int shift_by
)
2911 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
2912 f
->output_data
.x
->normal_gc
,
2913 x
, y
, width
, height
,
2917 /* Delete N glyphs at the nominal cursor position. Not implemented
2921 x_delete_glyphs (struct frame
*f
, register int n
)
2927 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2928 If they are <= 0, this is probably an error. */
2931 x_clear_area (Display
*dpy
, Window window
, int x
, int y
, int width
, int height
)
2933 eassert (width
> 0 && height
> 0);
2934 XClearArea (dpy
, window
, x
, y
, width
, height
, False
);
2938 /* Clear an entire frame. */
2941 x_clear_frame (struct frame
*f
)
2943 /* Clearing the frame will erase any cursor, so mark them all as no
2945 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2949 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
2951 /* We have to clear the scroll bars. If we have changed colors or
2952 something like that, then they should be notified. */
2953 x_scroll_bar_clear (f
);
2955 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
2956 /* Make sure scroll bars are redrawn. As they aren't redrawn by
2957 redisplay, do it here. */
2958 if (FRAME_GTK_WIDGET (f
))
2959 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
2962 XFlush (FRAME_X_DISPLAY (f
));
2969 /* Invert the middle quarter of the frame for .15 sec. */
2972 XTflash (struct frame
*f
)
2978 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
2979 when the scroll bars and the edit widget share the same X window. */
2980 GdkWindow
*window
= gtk_widget_get_window (FRAME_GTK_WIDGET (f
));
2982 cairo_t
*cr
= gdk_cairo_create (window
);
2983 cairo_set_source_rgb (cr
, 1, 1, 1);
2984 cairo_set_operator (cr
, CAIRO_OPERATOR_DIFFERENCE
);
2985 #define XFillRectangle(d, win, gc, x, y, w, h) \
2987 cairo_rectangle (cr, x, y, w, h); \
2991 #else /* ! HAVE_GTK3 */
2994 vals
.foreground
.pixel
= (FRAME_FOREGROUND_PIXEL (f
)
2995 ^ FRAME_BACKGROUND_PIXEL (f
));
2996 vals
.function
= GDK_XOR
;
2997 gc
= gdk_gc_new_with_values (window
,
2998 &vals
, GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
);
2999 #define XFillRectangle(d, win, gc, x, y, w, h) \
3000 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
3001 #endif /* ! HAVE_GTK3 */
3002 #else /* ! USE_GTK */
3005 /* Create a GC that will use the GXxor function to flip foreground
3006 pixels into background pixels. */
3010 values
.function
= GXxor
;
3011 values
.foreground
= (FRAME_FOREGROUND_PIXEL (f
)
3012 ^ FRAME_BACKGROUND_PIXEL (f
));
3014 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3015 GCFunction
| GCForeground
, &values
);
3019 /* Get the height not including a menu bar widget. */
3020 int height
= FRAME_PIXEL_HEIGHT (f
);
3021 /* Height of each line to flash. */
3022 int flash_height
= FRAME_LINE_HEIGHT (f
);
3023 /* These will be the left and right margins of the rectangles. */
3024 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3025 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3026 int width
= flash_right
- flash_left
;
3028 /* If window is tall, flash top and bottom line. */
3029 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3031 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3033 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3034 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3035 width
, flash_height
);
3036 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3038 (height
- flash_height
3039 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3040 width
, flash_height
);
3044 /* If it is short, flash it all. */
3045 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3046 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3047 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3052 struct timespec delay
= make_timespec (0, 150 * 1000 * 1000);
3053 struct timespec wakeup
= timespec_add (current_timespec (), delay
);
3055 /* Keep waiting until past the time wakeup or any input gets
3057 while (! detect_input_pending ())
3059 struct timespec current
= current_timespec ();
3060 struct timespec timeout
;
3062 /* Break if result would not be positive. */
3063 if (timespec_cmp (wakeup
, current
) <= 0)
3066 /* How long `select' should wait. */
3067 timeout
= make_timespec (0, 10 * 1000 * 1000);
3069 /* Try to wait that long--but we might wake up sooner. */
3070 pselect (0, NULL
, NULL
, NULL
, &timeout
, NULL
);
3074 /* If window is tall, flash top and bottom line. */
3075 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3077 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3079 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3080 + FRAME_TOP_MARGIN_HEIGHT (f
)),
3081 width
, flash_height
);
3082 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3084 (height
- flash_height
3085 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3086 width
, flash_height
);
3089 /* If it is short, flash it all. */
3090 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3091 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3092 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3098 g_object_unref (G_OBJECT (gc
));
3100 #undef XFillRectangle
3102 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
3113 XTtoggle_invisible_pointer (struct frame
*f
, int invisible
)
3116 FRAME_DISPLAY_INFO (f
)->toggle_visible_pointer (f
, invisible
);
3121 /* Make audible bell. */
3124 XTring_bell (struct frame
*f
)
3126 if (FRAME_X_DISPLAY (f
))
3134 XkbBell (FRAME_X_DISPLAY (f
), None
, 0, None
);
3136 XBell (FRAME_X_DISPLAY (f
), 0);
3138 XFlush (FRAME_X_DISPLAY (f
));
3144 /***********************************************************************
3146 ***********************************************************************/
3148 /* Perform an insert-lines or delete-lines operation, inserting N
3149 lines or deleting -N lines at vertical position VPOS. */
3152 x_ins_del_lines (struct frame
*f
, int vpos
, int n
)
3158 /* Scroll part of the display as described by RUN. */
3161 x_scroll_run (struct window
*w
, struct run
*run
)
3163 struct frame
*f
= XFRAME (w
->frame
);
3164 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3166 /* Get frame-relative bounding box of the text display area of W,
3167 without mode lines. Include in this box the left and right
3169 window_box (w
, ANY_AREA
, &x
, &y
, &width
, &height
);
3171 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3172 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3173 bottom_y
= y
+ height
;
3177 /* Scrolling up. Make sure we don't copy part of the mode
3178 line at the bottom. */
3179 if (from_y
+ run
->height
> bottom_y
)
3180 height
= bottom_y
- from_y
;
3182 height
= run
->height
;
3186 /* Scrolling down. Make sure we don't copy over the mode line.
3188 if (to_y
+ run
->height
> bottom_y
)
3189 height
= bottom_y
- to_y
;
3191 height
= run
->height
;
3196 /* Cursor off. Will be switched on again in x_update_window_end. */
3199 XCopyArea (FRAME_X_DISPLAY (f
),
3200 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
3201 f
->output_data
.x
->normal_gc
,
3211 /***********************************************************************
3213 ***********************************************************************/
3217 frame_highlight (struct frame
*f
)
3219 /* We used to only do this if Vx_no_window_manager was non-nil, but
3220 the ICCCM (section 4.1.6) says that the window's border pixmap
3221 and border pixel are window attributes which are "private to the
3222 client", so we can always change it to whatever we want. */
3224 /* I recently started to get errors in this XSetWindowBorder, depending on
3225 the window-manager in use, tho something more is at play since I've been
3226 using that same window-manager binary for ever. Let's not crash just
3227 because of this (bug#9310). */
3228 x_catch_errors (FRAME_X_DISPLAY (f
));
3229 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3230 f
->output_data
.x
->border_pixel
);
3231 x_uncatch_errors ();
3233 x_update_cursor (f
, 1);
3234 x_set_frame_alpha (f
);
3238 frame_unhighlight (struct frame
*f
)
3240 /* We used to only do this if Vx_no_window_manager was non-nil, but
3241 the ICCCM (section 4.1.6) says that the window's border pixmap
3242 and border pixel are window attributes which are "private to the
3243 client", so we can always change it to whatever we want. */
3245 /* Same as above for XSetWindowBorder (bug#9310). */
3246 x_catch_errors (FRAME_X_DISPLAY (f
));
3247 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3248 f
->output_data
.x
->border_tile
);
3249 x_uncatch_errors ();
3251 x_update_cursor (f
, 1);
3252 x_set_frame_alpha (f
);
3255 /* The focus has changed. Update the frames as necessary to reflect
3256 the new situation. Note that we can't change the selected frame
3257 here, because the Lisp code we are interrupting might become confused.
3258 Each event gets marked with the frame in which it occurred, so the
3259 Lisp code can tell when the switch took place by examining the events. */
3262 x_new_focus_frame (struct x_display_info
*dpyinfo
, struct frame
*frame
)
3264 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3266 if (frame
!= dpyinfo
->x_focus_frame
)
3268 /* Set this before calling other routines, so that they see
3269 the correct value of x_focus_frame. */
3270 dpyinfo
->x_focus_frame
= frame
;
3272 if (old_focus
&& old_focus
->auto_lower
)
3273 x_lower_frame (old_focus
);
3275 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3276 dpyinfo
->x_pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3278 dpyinfo
->x_pending_autoraise_frame
= NULL
;
3281 x_frame_rehighlight (dpyinfo
);
3284 /* Handle FocusIn and FocusOut state changes for FRAME.
3285 If FRAME has focus and there exists more than one frame, puts
3286 a FOCUS_IN_EVENT into *BUFP. */
3289 x_focus_changed (int type
, int state
, struct x_display_info
*dpyinfo
, struct frame
*frame
, struct input_event
*bufp
)
3291 if (type
== FocusIn
)
3293 if (dpyinfo
->x_focus_event_frame
!= frame
)
3295 x_new_focus_frame (dpyinfo
, frame
);
3296 dpyinfo
->x_focus_event_frame
= frame
;
3298 /* Don't stop displaying the initial startup message
3299 for a switch-frame event we don't need. */
3300 /* When run as a daemon, Vterminal_frame is always NIL. */
3301 bufp
->arg
= (((NILP (Vterminal_frame
)
3302 || ! FRAME_X_P (XFRAME (Vterminal_frame
))
3303 || EQ (Fdaemonp (), Qt
))
3304 && CONSP (Vframe_list
)
3305 && !NILP (XCDR (Vframe_list
)))
3307 bufp
->kind
= FOCUS_IN_EVENT
;
3308 XSETFRAME (bufp
->frame_or_window
, frame
);
3311 frame
->output_data
.x
->focus_state
|= state
;
3314 if (FRAME_XIC (frame
))
3315 XSetICFocus (FRAME_XIC (frame
));
3318 else if (type
== FocusOut
)
3320 frame
->output_data
.x
->focus_state
&= ~state
;
3322 if (dpyinfo
->x_focus_event_frame
== frame
)
3324 dpyinfo
->x_focus_event_frame
= 0;
3325 x_new_focus_frame (dpyinfo
, 0);
3327 bufp
->kind
= FOCUS_OUT_EVENT
;
3328 XSETFRAME (bufp
->frame_or_window
, frame
);
3332 if (FRAME_XIC (frame
))
3333 XUnsetICFocus (FRAME_XIC (frame
));
3335 if (frame
->pointer_invisible
)
3336 XTtoggle_invisible_pointer (frame
, 0);
3340 /* Return the Emacs frame-object corresponding to an X window.
3341 It could be the frame's main window or an icon window. */
3343 static struct frame
*
3344 x_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
3346 Lisp_Object tail
, frame
;
3352 FOR_EACH_FRAME (tail
, frame
)
3355 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
3357 if (f
->output_data
.x
->hourglass_window
== wdesc
)
3359 #ifdef USE_X_TOOLKIT
3360 if ((f
->output_data
.x
->edit_widget
3361 && XtWindow (f
->output_data
.x
->edit_widget
) == wdesc
)
3362 /* A tooltip frame? */
3363 || (!f
->output_data
.x
->edit_widget
3364 && FRAME_X_WINDOW (f
) == wdesc
)
3365 || f
->output_data
.x
->icon_desc
== wdesc
)
3367 #else /* not USE_X_TOOLKIT */
3369 if (f
->output_data
.x
->edit_widget
)
3371 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
3372 struct x_output
*x
= f
->output_data
.x
;
3373 if (gwdesc
!= 0 && gwdesc
== x
->edit_widget
)
3376 #endif /* USE_GTK */
3377 if (FRAME_X_WINDOW (f
) == wdesc
3378 || f
->output_data
.x
->icon_desc
== wdesc
)
3380 #endif /* not USE_X_TOOLKIT */
3385 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3387 /* Like x_window_to_frame but also compares the window with the widget's
3390 static struct frame
*
3391 x_any_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
3393 Lisp_Object tail
, frame
;
3394 struct frame
*f
, *found
= NULL
;
3400 FOR_EACH_FRAME (tail
, frame
)
3405 if (FRAME_X_P (f
) && FRAME_DISPLAY_INFO (f
) == dpyinfo
)
3407 /* This frame matches if the window is any of its widgets. */
3408 x
= f
->output_data
.x
;
3409 if (x
->hourglass_window
== wdesc
)
3414 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
3416 && gtk_widget_get_toplevel (gwdesc
) == x
->widget
)
3419 if (wdesc
== XtWindow (x
->widget
)
3420 || wdesc
== XtWindow (x
->column_widget
)
3421 || wdesc
== XtWindow (x
->edit_widget
))
3423 /* Match if the window is this frame's menubar. */
3424 else if (lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
3428 else if (FRAME_X_WINDOW (f
) == wdesc
)
3429 /* A tooltip frame. */
3437 /* Likewise, but consider only the menu bar widget. */
3439 static struct frame
*
3440 x_menubar_window_to_frame (struct x_display_info
*dpyinfo
,
3441 const XEvent
*event
)
3443 Window wdesc
= event
->xany
.window
;
3444 Lisp_Object tail
, frame
;
3451 FOR_EACH_FRAME (tail
, frame
)
3454 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
3456 x
= f
->output_data
.x
;
3458 if (x
->menubar_widget
&& xg_event_is_for_menubar (f
, event
))
3461 /* Match if the window is this frame's menubar. */
3462 if (x
->menubar_widget
3463 && lw_window_is_in_menubar (wdesc
, x
->menubar_widget
))
3470 /* Return the frame whose principal (outermost) window is WDESC.
3471 If WDESC is some other (smaller) window, we return 0. */
3474 x_top_window_to_frame (struct x_display_info
*dpyinfo
, int wdesc
)
3476 Lisp_Object tail
, frame
;
3483 FOR_EACH_FRAME (tail
, frame
)
3486 if (!FRAME_X_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
3488 x
= f
->output_data
.x
;
3492 /* This frame matches if the window is its topmost widget. */
3494 GtkWidget
*gwdesc
= xg_win_to_widget (dpyinfo
->display
, wdesc
);
3495 if (gwdesc
== x
->widget
)
3498 if (wdesc
== XtWindow (x
->widget
))
3502 else if (FRAME_X_WINDOW (f
) == wdesc
)
3503 /* Tooltip frame. */
3509 #else /* !USE_X_TOOLKIT && !USE_GTK */
3511 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
3512 #define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
3514 #endif /* USE_X_TOOLKIT || USE_GTK */
3516 /* The focus may have changed. Figure out if it is a real focus change,
3517 by checking both FocusIn/Out and Enter/LeaveNotify events.
3519 Returns FOCUS_IN_EVENT event in *BUFP. */
3522 x_detect_focus_change (struct x_display_info
*dpyinfo
, struct frame
*frame
,
3523 const XEvent
*event
, struct input_event
*bufp
)
3528 switch (event
->type
)
3533 struct frame
*focus_frame
= dpyinfo
->x_focus_event_frame
;
3535 = focus_frame
? focus_frame
->output_data
.x
->focus_state
: 0;
3537 if (event
->xcrossing
.detail
!= NotifyInferior
3538 && event
->xcrossing
.focus
3539 && ! (focus_state
& FOCUS_EXPLICIT
))
3540 x_focus_changed ((event
->type
== EnterNotify
? FocusIn
: FocusOut
),
3542 dpyinfo
, frame
, bufp
);
3548 x_focus_changed (event
->type
,
3549 (event
->xfocus
.detail
== NotifyPointer
?
3550 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3551 dpyinfo
, frame
, bufp
);
3555 if (event
->xclient
.message_type
== dpyinfo
->Xatom_XEMBED
)
3557 enum xembed_message msg
= event
->xclient
.data
.l
[1];
3558 x_focus_changed ((msg
== XEMBED_FOCUS_IN
? FocusIn
: FocusOut
),
3559 FOCUS_EXPLICIT
, dpyinfo
, frame
, bufp
);
3566 #if !defined USE_X_TOOLKIT && !defined USE_GTK
3567 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3570 x_mouse_leave (struct x_display_info
*dpyinfo
)
3572 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3576 /* The focus has changed, or we have redirected a frame's focus to
3577 another frame (this happens when a frame uses a surrogate
3578 mini-buffer frame). Shift the highlight as appropriate.
3580 The FRAME argument doesn't necessarily have anything to do with which
3581 frame is being highlighted or un-highlighted; we only use it to find
3582 the appropriate X display info. */
3585 XTframe_rehighlight (struct frame
*frame
)
3587 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame
));
3591 x_frame_rehighlight (struct x_display_info
*dpyinfo
)
3593 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3595 if (dpyinfo
->x_focus_frame
)
3597 dpyinfo
->x_highlight_frame
3598 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3599 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3600 : dpyinfo
->x_focus_frame
);
3601 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3603 fset_focus_frame (dpyinfo
->x_focus_frame
, Qnil
);
3604 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3608 dpyinfo
->x_highlight_frame
= 0;
3610 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3613 frame_unhighlight (old_highlight
);
3614 if (dpyinfo
->x_highlight_frame
)
3615 frame_highlight (dpyinfo
->x_highlight_frame
);
3621 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3623 /* Initialize mode_switch_bit and modifier_meaning. */
3625 x_find_modifier_meanings (struct x_display_info
*dpyinfo
)
3627 int min_code
, max_code
;
3630 XModifierKeymap
*mods
;
3632 dpyinfo
->meta_mod_mask
= 0;
3633 dpyinfo
->shift_lock_mask
= 0;
3634 dpyinfo
->alt_mod_mask
= 0;
3635 dpyinfo
->super_mod_mask
= 0;
3636 dpyinfo
->hyper_mod_mask
= 0;
3638 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3640 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3641 min_code
, max_code
- min_code
+ 1,
3643 mods
= XGetModifierMapping (dpyinfo
->display
);
3645 /* Scan the modifier table to see which modifier bits the Meta and
3646 Alt keysyms are on. */
3648 int row
, col
; /* The row and column in the modifier table. */
3649 int found_alt_or_meta
;
3651 for (row
= 3; row
< 8; row
++)
3653 found_alt_or_meta
= 0;
3654 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3656 KeyCode code
= mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3658 /* Zeroes are used for filler. Skip them. */
3662 /* Are any of this keycode's keysyms a meta key? */
3666 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3668 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3674 found_alt_or_meta
= 1;
3675 dpyinfo
->meta_mod_mask
|= (1 << row
);
3680 found_alt_or_meta
= 1;
3681 dpyinfo
->alt_mod_mask
|= (1 << row
);
3686 if (!found_alt_or_meta
)
3687 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3688 code_col
= syms_per_code
;
3689 col
= mods
->max_keypermod
;
3694 if (!found_alt_or_meta
)
3695 dpyinfo
->super_mod_mask
|= (1 << row
);
3696 code_col
= syms_per_code
;
3697 col
= mods
->max_keypermod
;
3701 /* Ignore this if it's not on the lock modifier. */
3702 if (!found_alt_or_meta
&& ((1 << row
) == LockMask
))
3703 dpyinfo
->shift_lock_mask
= LockMask
;
3704 code_col
= syms_per_code
;
3705 col
= mods
->max_keypermod
;
3714 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3715 if (! dpyinfo
->meta_mod_mask
)
3717 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3718 dpyinfo
->alt_mod_mask
= 0;
3721 /* If some keys are both alt and meta,
3722 make them just meta, not alt. */
3723 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3725 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3729 XFreeModifiermap (mods
);
3732 /* Convert between the modifier bits X uses and the modifier bits
3736 x_x_to_emacs_modifiers (struct x_display_info
*dpyinfo
, int state
)
3738 int mod_meta
= meta_modifier
;
3739 int mod_alt
= alt_modifier
;
3740 int mod_hyper
= hyper_modifier
;
3741 int mod_super
= super_modifier
;
3744 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3745 if (INTEGERP (tem
)) mod_alt
= XINT (tem
) & INT_MAX
;
3746 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3747 if (INTEGERP (tem
)) mod_meta
= XINT (tem
) & INT_MAX
;
3748 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3749 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
) & INT_MAX
;
3750 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3751 if (INTEGERP (tem
)) mod_super
= XINT (tem
) & INT_MAX
;
3753 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
3754 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
3755 | ((state
& dpyinfo
->meta_mod_mask
) ? mod_meta
: 0)
3756 | ((state
& dpyinfo
->alt_mod_mask
) ? mod_alt
: 0)
3757 | ((state
& dpyinfo
->super_mod_mask
) ? mod_super
: 0)
3758 | ((state
& dpyinfo
->hyper_mod_mask
) ? mod_hyper
: 0));
3762 x_emacs_to_x_modifiers (struct x_display_info
*dpyinfo
, EMACS_INT state
)
3764 EMACS_INT mod_meta
= meta_modifier
;
3765 EMACS_INT mod_alt
= alt_modifier
;
3766 EMACS_INT mod_hyper
= hyper_modifier
;
3767 EMACS_INT mod_super
= super_modifier
;
3771 tem
= Fget (Vx_alt_keysym
, Qmodifier_value
);
3772 if (INTEGERP (tem
)) mod_alt
= XINT (tem
);
3773 tem
= Fget (Vx_meta_keysym
, Qmodifier_value
);
3774 if (INTEGERP (tem
)) mod_meta
= XINT (tem
);
3775 tem
= Fget (Vx_hyper_keysym
, Qmodifier_value
);
3776 if (INTEGERP (tem
)) mod_hyper
= XINT (tem
);
3777 tem
= Fget (Vx_super_keysym
, Qmodifier_value
);
3778 if (INTEGERP (tem
)) mod_super
= XINT (tem
);
3781 return ( ((state
& mod_alt
) ? dpyinfo
->alt_mod_mask
: 0)
3782 | ((state
& mod_super
) ? dpyinfo
->super_mod_mask
: 0)
3783 | ((state
& mod_hyper
) ? dpyinfo
->hyper_mod_mask
: 0)
3784 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3785 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3786 | ((state
& mod_meta
) ? dpyinfo
->meta_mod_mask
: 0));
3789 /* Convert a keysym to its name. */
3792 x_get_keysym_name (int keysym
)
3797 value
= XKeysymToString (keysym
);
3803 /* Mouse clicks and mouse movement. Rah.
3805 Formerly, we used PointerMotionHintMask (in standard_event_mask)
3806 so that we would have to call XQueryPointer after each MotionNotify
3807 event to ask for another such event. However, this made mouse tracking
3808 slow, and there was a bug that made it eventually stop.
3810 Simply asking for MotionNotify all the time seems to work better.
3812 In order to avoid asking for motion events and then throwing most
3813 of them away or busy-polling the server for mouse positions, we ask
3814 the server for pointer motion hints. This means that we get only
3815 one event per group of mouse movements. "Groups" are delimited by
3816 other kinds of events (focus changes and button clicks, for
3817 example), or by XQueryPointer calls; when one of these happens, we
3818 get another MotionNotify event the next time the mouse moves. This
3819 is at least as efficient as getting motion events when mouse
3820 tracking is on, and I suspect only negligibly worse when tracking
3823 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3825 If the event is a button press, then note that we have grabbed
3829 construct_mouse_click (struct input_event
*result
,
3830 const XButtonEvent
*event
,
3833 /* Make the event type NO_EVENT; we'll change that when we decide
3835 result
->kind
= MOUSE_CLICK_EVENT
;
3836 result
->code
= event
->button
- Button1
;
3837 result
->timestamp
= event
->time
;
3838 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f
),
3840 | (event
->type
== ButtonRelease
3844 XSETINT (result
->x
, event
->x
);
3845 XSETINT (result
->y
, event
->y
);
3846 XSETFRAME (result
->frame_or_window
, f
);
3851 /* Function to report a mouse movement to the mainstream Emacs code.
3852 The input handler calls this.
3854 We have received a mouse movement event, which is given in *event.
3855 If the mouse is over a different glyph than it was last time, tell
3856 the mainstream emacs code by setting mouse_moved. If not, ask for
3857 another motion event, so we can check again the next time it moves. */
3860 note_mouse_movement (struct frame
*frame
, const XMotionEvent
*event
)
3863 struct x_display_info
*dpyinfo
;
3865 if (!FRAME_X_OUTPUT (frame
))
3868 dpyinfo
= FRAME_DISPLAY_INFO (frame
);
3869 dpyinfo
->last_mouse_movement_time
= event
->time
;
3870 dpyinfo
->last_mouse_motion_frame
= frame
;
3871 dpyinfo
->last_mouse_motion_x
= event
->x
;
3872 dpyinfo
->last_mouse_motion_y
= event
->y
;
3874 if (event
->window
!= FRAME_X_WINDOW (frame
))
3876 frame
->mouse_moved
= 1;
3877 dpyinfo
->last_mouse_scroll_bar
= NULL
;
3878 note_mouse_highlight (frame
, -1, -1);
3879 dpyinfo
->last_mouse_glyph_frame
= NULL
;
3884 /* Has the mouse moved off the glyph it was on at the last sighting? */
3885 r
= &dpyinfo
->last_mouse_glyph
;
3886 if (frame
!= dpyinfo
->last_mouse_glyph_frame
3887 || event
->x
< r
->x
|| event
->x
>= r
->x
+ r
->width
3888 || event
->y
< r
->y
|| event
->y
>= r
->y
+ r
->height
)
3890 frame
->mouse_moved
= 1;
3891 dpyinfo
->last_mouse_scroll_bar
= NULL
;
3892 note_mouse_highlight (frame
, event
->x
, event
->y
);
3893 /* Remember which glyph we're now on. */
3894 remember_mouse_glyph (frame
, event
->x
, event
->y
, r
);
3895 dpyinfo
->last_mouse_glyph_frame
= frame
;
3902 /* Return the current position of the mouse.
3903 *FP should be a frame which indicates which display to ask about.
3905 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3906 and *PART to the frame, window, and scroll bar part that the mouse
3907 is over. Set *X and *Y to the portion and whole of the mouse's
3908 position on the scroll bar.
3910 If the mouse movement started elsewhere, set *FP to the frame the
3911 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3914 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
3915 was at this position.
3917 Don't store anything if we don't have a valid set of values to report.
3919 This clears the mouse_moved flag, so we can wait for the next mouse
3923 XTmouse_position (struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
3924 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
3928 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
3932 if (dpyinfo
->last_mouse_scroll_bar
&& insist
== 0)
3933 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, timestamp
);
3939 Window dummy_window
;
3942 Lisp_Object frame
, tail
;
3944 /* Clear the mouse-moved flag for every frame on this display. */
3945 FOR_EACH_FRAME (tail
, frame
)
3946 if (FRAME_X_P (XFRAME (frame
))
3947 && FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
3948 XFRAME (frame
)->mouse_moved
= 0;
3950 dpyinfo
->last_mouse_scroll_bar
= NULL
;
3952 /* Figure out which root window we're on. */
3953 XQueryPointer (FRAME_X_DISPLAY (*fp
),
3954 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
3956 /* The root window which contains the pointer. */
3959 /* Trash which we can't trust if the pointer is on
3960 a different screen. */
3963 /* The position on that root window. */
3966 /* More trash we can't trust. */
3969 /* Modifier keys and pointer buttons, about which
3971 (unsigned int *) &dummy
);
3973 /* Now we have a position on the root; find the innermost window
3974 containing the pointer. */
3978 int parent_x
= 0, parent_y
= 0;
3982 /* XTranslateCoordinates can get errors if the window
3983 structure is changing at the same time this function
3984 is running. So at least we must not crash from them. */
3986 x_catch_errors (FRAME_X_DISPLAY (*fp
));
3988 if (x_mouse_grabbed (dpyinfo
))
3990 /* If mouse was grabbed on a frame, give coords for that frame
3991 even if the mouse is now outside it. */
3992 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
3998 FRAME_X_WINDOW (dpyinfo
->last_mouse_frame
),
4000 /* From-position, to-position. */
4001 root_x
, root_y
, &win_x
, &win_y
,
4005 f1
= dpyinfo
->last_mouse_frame
;
4011 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
4013 /* From-window, to-window. */
4016 /* From-position, to-position. */
4017 root_x
, root_y
, &win_x
, &win_y
,
4022 if (child
== None
|| child
== win
)
4025 /* We don't wan't to know the innermost window. We
4026 want the edit window. For non-Gtk+ the innermost
4027 window is the edit window. For Gtk+ it might not
4028 be. It might be the tool bar for example. */
4029 if (x_window_to_frame (dpyinfo
, win
))
4037 /* Now we know that:
4038 win is the innermost window containing the pointer
4039 (XTC says it has no child containing the pointer),
4040 win_x and win_y are the pointer's position in it
4041 (XTC did this the last time through), and
4042 parent_x and parent_y are the pointer's position in win's parent.
4043 (They are what win_x and win_y were when win was child.
4044 If win is the root window, it has no parent, and
4045 parent_{x,y} are invalid, but that's okay, because we'll
4046 never use them in that case.) */
4049 /* We don't wan't to know the innermost window. We
4050 want the edit window. */
4051 f1
= x_window_to_frame (dpyinfo
, win
);
4053 /* Is win one of our frames? */
4054 f1
= x_any_window_to_frame (dpyinfo
, win
);
4057 #ifdef USE_X_TOOLKIT
4058 /* If we end up with the menu bar window, say it's not
4061 && f1
->output_data
.x
->menubar_widget
4062 && win
== XtWindow (f1
->output_data
.x
->menubar_widget
))
4064 #endif /* USE_X_TOOLKIT */
4067 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
4070 x_uncatch_errors ();
4072 /* If not, is it one of our scroll bars? */
4075 struct scroll_bar
*bar
;
4077 bar
= x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp
), win
);
4081 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4087 if (f1
== 0 && insist
> 0)
4088 f1
= SELECTED_FRAME ();
4092 /* Ok, we found a frame. Store all the values.
4093 last_mouse_glyph is a rectangle used to reduce the
4094 generation of mouse events. To not miss any motion
4095 events, we must divide the frame into rectangles of the
4096 size of the smallest character that could be displayed
4097 on it, i.e. into the same rectangles that matrices on
4098 the frame are divided into. */
4100 /* FIXME: what if F1 is not an X frame? */
4101 dpyinfo
= FRAME_DISPLAY_INFO (f1
);
4102 remember_mouse_glyph (f1
, win_x
, win_y
, &dpyinfo
->last_mouse_glyph
);
4103 dpyinfo
->last_mouse_glyph_frame
= f1
;
4108 XSETINT (*x
, win_x
);
4109 XSETINT (*y
, win_y
);
4110 *timestamp
= dpyinfo
->last_mouse_movement_time
;
4120 /***********************************************************************
4122 ***********************************************************************/
4124 /* Scroll bar support. */
4126 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4128 This can be called in GC, so we have to make sure to strip off mark
4131 static struct scroll_bar
*
4132 x_window_to_scroll_bar (Display
*display
, Window window_id
)
4134 Lisp_Object tail
, frame
;
4136 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4137 window_id
= (Window
) xg_get_scroll_id_for_window (display
, window_id
);
4138 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4140 FOR_EACH_FRAME (tail
, frame
)
4142 Lisp_Object bar
, condemned
;
4144 if (! FRAME_X_P (XFRAME (frame
)))
4147 /* Scan this frame's scroll bar list for a scroll bar with the
4149 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
4150 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
4151 /* This trick allows us to search both the ordinary and
4152 condemned scroll bar lists with one loop. */
4153 ! NILP (bar
) || (bar
= condemned
,
4156 bar
= XSCROLL_BAR (bar
)->next
)
4157 if (XSCROLL_BAR (bar
)->x_window
== window_id
&&
4158 FRAME_X_DISPLAY (XFRAME (frame
)) == display
)
4159 return XSCROLL_BAR (bar
);
4166 #if defined USE_LUCID
4168 /* Return the Lucid menu bar WINDOW is part of. Return null
4169 if WINDOW is not part of a menu bar. */
4172 x_window_to_menu_bar (Window window
)
4174 Lisp_Object tail
, frame
;
4176 FOR_EACH_FRAME (tail
, frame
)
4177 if (FRAME_X_P (XFRAME (frame
)))
4179 Widget menu_bar
= XFRAME (frame
)->output_data
.x
->menubar_widget
;
4181 if (menu_bar
&& xlwmenu_window_p (menu_bar
, window
))
4187 #endif /* USE_LUCID */
4190 /************************************************************************
4192 ************************************************************************/
4194 #ifdef USE_TOOLKIT_SCROLL_BARS
4196 static void x_send_scroll_bar_event (Lisp_Object
, int, int, int);
4198 /* Lisp window being scrolled. Set when starting to interact with
4199 a toolkit scroll bar, reset to nil when ending the interaction. */
4201 static Lisp_Object window_being_scrolled
;
4203 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4204 that movements of 1/20 of the screen size are mapped to up/down. */
4207 /* Id of action hook installed for scroll bars. */
4209 static XtActionHookId action_hook_id
;
4211 static Boolean xaw3d_arrow_scroll
;
4213 /* Whether the drag scrolling maintains the mouse at the top of the
4214 thumb. If not, resizing the thumb needs to be done more carefully
4215 to avoid jerkiness. */
4217 static Boolean xaw3d_pick_top
;
4219 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4220 bars are used.. The hook is responsible for detecting when
4221 the user ends an interaction with the scroll bar, and generates
4222 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4225 xt_action_hook (Widget widget
, XtPointer client_data
, String action_name
,
4226 XEvent
*event
, String
*params
, Cardinal
*num_params
)
4229 const char *end_action
;
4232 scroll_bar_p
= XmIsScrollBar (widget
);
4233 end_action
= "Release";
4234 #else /* !USE_MOTIF i.e. use Xaw */
4235 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
4236 end_action
= "EndScroll";
4237 #endif /* USE_MOTIF */
4240 && strcmp (action_name
, end_action
) == 0
4241 && WINDOWP (window_being_scrolled
))
4244 struct scroll_bar
*bar
;
4246 x_send_scroll_bar_event (window_being_scrolled
,
4247 scroll_bar_end_scroll
, 0, 0);
4248 w
= XWINDOW (window_being_scrolled
);
4249 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4251 if (bar
->dragging
!= -1)
4254 /* The thumb size is incorrect while dragging: fix it. */
4255 set_vertical_scroll_bar (w
);
4257 window_being_scrolled
= Qnil
;
4258 #if defined (USE_LUCID)
4259 bar
->last_seen_part
= scroll_bar_nowhere
;
4261 /* Xt timeouts no longer needed. */
4262 toolkit_scroll_bar_interaction
= 0;
4265 #endif /* not USE_GTK */
4267 /* Send a client message with message type Xatom_Scrollbar for a
4268 scroll action to the frame of WINDOW. PART is a value identifying
4269 the part of the scroll bar that was clicked on. PORTION is the
4270 amount to scroll of a whole of WHOLE. */
4273 x_send_scroll_bar_event (Lisp_Object window
, int part
, int portion
, int whole
)
4276 XClientMessageEvent
*ev
= &event
.xclient
;
4277 struct window
*w
= XWINDOW (window
);
4278 struct frame
*f
= XFRAME (w
->frame
);
4279 intptr_t iw
= (intptr_t) w
;
4280 enum { BITS_PER_INTPTR
= CHAR_BIT
* sizeof iw
};
4281 verify (BITS_PER_INTPTR
<= 64);
4282 int sign_shift
= BITS_PER_INTPTR
- 32;
4286 /* Construct a ClientMessage event to send to the frame. */
4287 ev
->type
= ClientMessage
;
4288 ev
->message_type
= FRAME_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
4289 ev
->display
= FRAME_X_DISPLAY (f
);
4290 ev
->window
= FRAME_X_WINDOW (f
);
4293 /* A 32-bit X client on a 64-bit X server can pass a window pointer
4294 as-is. A 64-bit client on a 32-bit X server is in trouble
4295 because a pointer does not fit and would be truncated while
4296 passing through the server. So use two slots and hope that X12
4297 will resolve such issues someday. */
4298 ev
->data
.l
[0] = iw
>> 31 >> 1;
4299 ev
->data
.l
[1] = sign_shift
<= 0 ? iw
: iw
<< sign_shift
>> sign_shift
;
4300 ev
->data
.l
[2] = part
;
4301 ev
->data
.l
[3] = portion
;
4302 ev
->data
.l
[4] = whole
;
4304 /* Make Xt timeouts work while the scroll bar is active. */
4305 #ifdef USE_X_TOOLKIT
4306 toolkit_scroll_bar_interaction
= 1;
4307 x_activate_timeout_atimer ();
4310 /* Setting the event mask to zero means that the message will
4311 be sent to the client that created the window, and if that
4312 window no longer exists, no event will be sent. */
4313 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
4318 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4322 x_scroll_bar_to_input_event (const XEvent
*event
,
4323 struct input_event
*ievent
)
4325 const XClientMessageEvent
*ev
= &event
->xclient
;
4329 /* See the comment in the function above. */
4330 intptr_t iw0
= ev
->data
.l
[0];
4331 intptr_t iw1
= ev
->data
.l
[1];
4332 intptr_t iw
= (iw0
<< 31 << 1) + (iw1
& 0xffffffffu
);
4333 w
= (struct window
*) iw
;
4335 XSETWINDOW (window
, w
);
4337 ievent
->kind
= SCROLL_BAR_CLICK_EVENT
;
4338 ievent
->frame_or_window
= window
;
4341 ievent
->timestamp
= CurrentTime
;
4344 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w
->frame
)));
4347 ievent
->part
= ev
->data
.l
[2];
4348 ievent
->x
= make_number (ev
->data
.l
[3]);
4349 ievent
->y
= make_number (ev
->data
.l
[4]);
4350 ievent
->modifiers
= 0;
4356 /* Minimum and maximum values used for Motif scroll bars. */
4358 #define XM_SB_MAX 10000000
4361 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4362 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4363 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4366 xm_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4368 struct scroll_bar
*bar
= client_data
;
4369 XmScrollBarCallbackStruct
*cs
= call_data
;
4370 int part
= -1, whole
= 0, portion
= 0;
4374 case XmCR_DECREMENT
:
4376 part
= scroll_bar_up_arrow
;
4379 case XmCR_INCREMENT
:
4381 part
= scroll_bar_down_arrow
;
4384 case XmCR_PAGE_DECREMENT
:
4386 part
= scroll_bar_above_handle
;
4389 case XmCR_PAGE_INCREMENT
:
4391 part
= scroll_bar_below_handle
;
4396 part
= scroll_bar_to_top
;
4399 case XmCR_TO_BOTTOM
:
4401 part
= scroll_bar_to_bottom
;
4408 /* Get the slider size. */
4410 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
4413 whole
= XM_SB_MAX
- slider_size
;
4414 portion
= min (cs
->value
, whole
);
4415 part
= scroll_bar_handle
;
4416 bar
->dragging
= cs
->value
;
4420 case XmCR_VALUE_CHANGED
:
4426 window_being_scrolled
= bar
->window
;
4427 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4431 #elif defined USE_GTK
4433 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4434 bar widget. DATA is a pointer to the scroll_bar structure. */
4437 xg_scroll_callback (GtkRange
*range
,
4438 GtkScrollType scroll
,
4442 struct scroll_bar
*bar
= user_data
;
4443 int part
= -1, whole
= 0, portion
= 0;
4444 GtkAdjustment
*adj
= GTK_ADJUSTMENT (gtk_range_get_adjustment (range
));
4445 struct frame
*f
= g_object_get_data (G_OBJECT (range
), XG_FRAME_DATA
);
4447 if (xg_ignore_gtk_scrollbar
) return FALSE
;
4451 case GTK_SCROLL_JUMP
:
4452 /* Buttons 1 2 or 3 must be grabbed. */
4453 if (FRAME_DISPLAY_INFO (f
)->grabbed
!= 0
4454 && FRAME_DISPLAY_INFO (f
)->grabbed
< (1 << 4))
4456 part
= scroll_bar_handle
;
4457 whole
= gtk_adjustment_get_upper (adj
) -
4458 gtk_adjustment_get_page_size (adj
);
4459 portion
= min ((int)value
, whole
);
4460 bar
->dragging
= portion
;
4463 case GTK_SCROLL_STEP_BACKWARD
:
4464 part
= scroll_bar_up_arrow
;
4467 case GTK_SCROLL_STEP_FORWARD
:
4468 part
= scroll_bar_down_arrow
;
4471 case GTK_SCROLL_PAGE_BACKWARD
:
4472 part
= scroll_bar_above_handle
;
4475 case GTK_SCROLL_PAGE_FORWARD
:
4476 part
= scroll_bar_below_handle
;
4483 window_being_scrolled
= bar
->window
;
4484 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4490 /* Callback for button release. Sets dragging to -1 when dragging is done. */
4493 xg_end_scroll_callback (GtkWidget
*widget
,
4494 GdkEventButton
*event
,
4497 struct scroll_bar
*bar
= user_data
;
4499 if (WINDOWP (window_being_scrolled
))
4501 x_send_scroll_bar_event (window_being_scrolled
,
4502 scroll_bar_end_scroll
, 0, 0);
4503 window_being_scrolled
= Qnil
;
4510 #else /* not USE_GTK and not USE_MOTIF */
4512 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4513 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4514 scroll bar struct. CALL_DATA is a pointer to a float saying where
4518 xaw_jump_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4520 struct scroll_bar
*bar
= client_data
;
4521 float *top_addr
= call_data
;
4522 float top
= *top_addr
;
4524 int whole
, portion
, height
;
4525 enum scroll_bar_part part
;
4527 /* Get the size of the thumb, a value between 0 and 1. */
4529 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
4533 portion
= shown
< 1 ? top
* whole
: 0;
4535 if (shown
< 1 && (eabs (top
+ shown
- 1) < 1.0f
/ height
))
4536 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4537 the bottom, so we force the scrolling whenever we see that we're
4538 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4539 we try to ensure that we always stay two pixels away from the
4541 part
= scroll_bar_down_arrow
;
4543 part
= scroll_bar_handle
;
4545 window_being_scrolled
= bar
->window
;
4546 bar
->dragging
= portion
;
4547 bar
->last_seen_part
= part
;
4548 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
4552 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4553 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4554 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4555 the scroll bar. CALL_DATA is an integer specifying the action that
4556 has taken place. Its magnitude is in the range 0..height of the
4557 scroll bar. Negative values mean scroll towards buffer start.
4558 Values < height of scroll bar mean line-wise movement. */
4561 xaw_scroll_callback (Widget widget
, XtPointer client_data
, XtPointer call_data
)
4563 struct scroll_bar
*bar
= client_data
;
4564 /* The position really is stored cast to a pointer. */
4565 int position
= (intptr_t) call_data
;
4567 enum scroll_bar_part part
;
4569 /* Get the height of the scroll bar. */
4571 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
4574 if (eabs (position
) >= height
)
4575 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
4577 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4578 it maps line-movement to call_data = max(5, height/20). */
4579 else if (xaw3d_arrow_scroll
&& eabs (position
) <= max (5, height
/ 20))
4580 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
4582 part
= scroll_bar_move_ratio
;
4584 window_being_scrolled
= bar
->window
;
4586 bar
->last_seen_part
= part
;
4587 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
4590 #endif /* not USE_GTK and not USE_MOTIF */
4592 #define SCROLL_BAR_NAME "verticalScrollBar"
4594 /* Create the widget for scroll bar BAR on frame F. Record the widget
4595 and X window of the scroll bar in BAR. */
4599 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
4601 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
4604 xg_create_scroll_bar (f
, bar
, G_CALLBACK (xg_scroll_callback
),
4605 G_CALLBACK (xg_end_scroll_callback
),
4610 #else /* not USE_GTK */
4613 x_create_toolkit_scroll_bar (struct frame
*f
, struct scroll_bar
*bar
)
4619 const char *scroll_bar_name
= SCROLL_BAR_NAME
;
4620 unsigned long pixel
;
4625 /* Set resources. Create the widget. */
4626 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4627 XtSetArg (av
[ac
], XmNminimum
, 0); ++ac
;
4628 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
4629 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
4630 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
4631 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
4632 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
4634 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4637 XtSetArg (av
[ac
], XmNforeground
, pixel
);
4641 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4644 XtSetArg (av
[ac
], XmNbackground
, pixel
);
4648 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
4649 (char *) scroll_bar_name
, av
, ac
);
4651 /* Add one callback for everything that can happen. */
4652 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
4654 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
4656 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
4658 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
4660 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
4662 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
4664 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
4667 /* Realize the widget. Only after that is the X window created. */
4668 XtRealizeWidget (widget
);
4670 /* Set the cursor to an arrow. I didn't find a resource to do that.
4671 And I'm wondering why it hasn't an arrow cursor by default. */
4672 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
4673 f
->output_data
.x
->nontext_cursor
);
4675 #else /* !USE_MOTIF i.e. use Xaw */
4677 /* Set resources. Create the widget. The background of the
4678 Xaw3d scroll bar widget is a little bit light for my taste.
4679 We don't alter it here to let users change it according
4680 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4681 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
4682 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
4683 /* For smoother scrolling with Xaw3d -sm */
4684 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4686 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
4689 XtSetArg (av
[ac
], XtNforeground
, pixel
);
4693 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4696 XtSetArg (av
[ac
], XtNbackground
, pixel
);
4700 /* Top/bottom shadow colors. */
4702 /* Allocate them, if necessary. */
4703 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1)
4705 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4708 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
4709 FRAME_X_COLORMAP (f
),
4710 &pixel
, 1.2, 0x8000))
4712 f
->output_data
.x
->scroll_bar_top_shadow_pixel
= pixel
;
4715 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4717 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4720 if (!x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
),
4721 FRAME_X_COLORMAP (f
),
4722 &pixel
, 0.6, 0x4000))
4724 f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
= pixel
;
4728 #ifdef XtNbeNiceToColormap
4729 /* Tell the toolkit about them. */
4730 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
== -1
4731 || f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
== -1)
4732 /* We tried to allocate a color for the top/bottom shadow, and
4733 failed, so tell Xaw3d to use dithering instead. */
4734 /* But only if we have a small colormap. Xaw3d can allocate nice
4737 XtSetArg (av
[ac
], XtNbeNiceToColormap
,
4738 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)) < 16);
4742 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4743 be more consistent with other emacs 3d colors, and since Xaw3d is
4744 not good at dealing with allocation failure. */
4746 /* This tells Xaw3d to use real colors instead of dithering for
4748 XtSetArg (av
[ac
], XtNbeNiceToColormap
, False
);
4751 /* Specify the colors. */
4752 pixel
= f
->output_data
.x
->scroll_bar_top_shadow_pixel
;
4755 XtSetArg (av
[ac
], XtNtopShadowPixel
, pixel
);
4758 pixel
= f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
;
4761 XtSetArg (av
[ac
], XtNbottomShadowPixel
, pixel
);
4767 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
4768 f
->output_data
.x
->edit_widget
, av
, ac
);
4771 char const *initial
= "";
4772 char const *val
= initial
;
4773 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
4774 #ifdef XtNarrowScrollbars
4775 XtNarrowScrollbars
, (XtPointer
) &xaw3d_arrow_scroll
,
4777 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
4778 if (xaw3d_arrow_scroll
|| val
== initial
)
4779 { /* ARROW_SCROLL */
4780 xaw3d_arrow_scroll
= True
;
4781 /* Isn't that just a personal preference ? --Stef */
4782 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
4786 /* Define callbacks. */
4787 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
4788 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
4791 /* Realize the widget. Only after that is the X window created. */
4792 XtRealizeWidget (widget
);
4794 #endif /* !USE_MOTIF */
4796 /* Install an action hook that lets us detect when the user
4797 finishes interacting with a scroll bar. */
4798 if (action_hook_id
== 0)
4799 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
4801 /* Remember X window and widget in the scroll bar vector. */
4802 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
4803 xwindow
= XtWindow (widget
);
4804 bar
->x_window
= xwindow
;
4808 #endif /* not USE_GTK */
4811 /* Set the thumb size and position of scroll bar BAR. We are currently
4812 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4816 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
, int whole
)
4818 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4821 #else /* not USE_GTK */
4823 x_set_toolkit_scroll_bar_thumb (struct scroll_bar
*bar
, int portion
, int position
,
4826 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4827 Widget widget
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
4834 if (scroll_bar_adjust_thumb_portion_p
)
4836 /* We use an estimate of 30 chars per line rather than the real
4837 `portion' value. This has the disadvantage that the thumb size
4838 is not very representative, but it makes our life a lot easier.
4839 Otherwise, we have to constantly adjust the thumb size, which
4840 we can't always do quickly enough: while dragging, the size of
4841 the thumb might prevent the user from dragging the thumb all the
4842 way to the end. but Motif and some versions of Xaw3d don't allow
4843 updating the thumb size while dragging. Also, even if we can update
4844 its size, the update will often happen too late.
4845 If you don't believe it, check out revision 1.650 of xterm.c to see
4846 what hoops we were going through and the still poor behavior we got. */
4847 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
4848 /* When the thumb is at the bottom, position == whole.
4849 So we need to increase `whole' to make space for the thumb. */
4857 top
= (float) position
/ whole
;
4858 shown
= (float) portion
/ whole
;
4861 if (bar
->dragging
== -1)
4865 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4866 is the scroll bar's maximum and MIN is the scroll bar's minimum
4868 size
= clip_to_bounds (1, shown
* XM_SB_MAX
, XM_SB_MAX
);
4870 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4871 value
= top
* XM_SB_MAX
;
4872 value
= min (value
, XM_SB_MAX
- size
);
4874 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
4876 #else /* !USE_MOTIF i.e. use Xaw */
4882 top
= (float) position
/ whole
;
4883 shown
= (float) portion
/ whole
;
4887 float old_top
, old_shown
;
4889 XtVaGetValues (widget
,
4890 XtNtopOfThumb
, &old_top
,
4891 XtNshown
, &old_shown
,
4895 /* Massage the top+shown values. */
4896 if (bar
->dragging
== -1 || bar
->last_seen_part
== scroll_bar_down_arrow
)
4897 top
= max (0, min (1, top
));
4900 #if ! defined (HAVE_XAW3D)
4901 /* With Xaw, 'top' values too closer to 1.0 may
4902 cause the thumb to disappear. Fix that. */
4903 top
= min (top
, 0.99f
);
4905 /* Keep two pixels available for moving the thumb down. */
4906 shown
= max (0, min (1 - top
- (2.0f
/ height
), shown
));
4907 #if ! defined (HAVE_XAW3D)
4908 /* Likewise with too small 'shown'. */
4909 shown
= max (shown
, 0.01f
);
4912 /* If the call to XawScrollbarSetThumb below doesn't seem to
4913 work, check that 'NARROWPROTO' is defined in src/config.h.
4914 If this is not so, most likely you need to fix configure. */
4915 if (top
!= old_top
|| shown
!= old_shown
)
4917 if (bar
->dragging
== -1)
4918 XawScrollbarSetThumb (widget
, top
, shown
);
4921 /* Try to make the scrolling a tad smoother. */
4922 if (!xaw3d_pick_top
)
4923 shown
= min (shown
, old_shown
);
4925 XawScrollbarSetThumb (widget
, top
, shown
);
4929 #endif /* !USE_MOTIF */
4933 #endif /* not USE_GTK */
4935 #endif /* USE_TOOLKIT_SCROLL_BARS */
4939 /************************************************************************
4940 Scroll bars, general
4941 ************************************************************************/
4943 /* Create a scroll bar and return the scroll bar vector for it. W is
4944 the Emacs window on which to create the scroll bar. TOP, LEFT,
4945 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4948 static struct scroll_bar
*
4949 x_scroll_bar_create (struct window
*w
, int top
, int left
, int width
, int height
)
4951 struct frame
*f
= XFRAME (w
->frame
);
4952 struct scroll_bar
*bar
4953 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar
, x_window
, PVEC_OTHER
);
4958 #ifdef USE_TOOLKIT_SCROLL_BARS
4959 x_create_toolkit_scroll_bar (f
, bar
);
4960 #else /* not USE_TOOLKIT_SCROLL_BARS */
4962 XSetWindowAttributes a
;
4966 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
4967 if (a
.background_pixel
== -1)
4968 a
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
4970 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
4971 | ButtonMotionMask
| PointerMotionHintMask
4973 a
.cursor
= FRAME_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
4975 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
4977 /* Clear the area of W that will serve as a scroll bar. This is
4978 for the case that a window has been split horizontally. In
4979 this case, no clear_frame is generated to reduce flickering. */
4980 if (width
> 0 && window_box_height (w
) > 0)
4981 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4982 left
, top
, width
, window_box_height (w
));
4984 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4985 /* Position and size of scroll bar. */
4986 left
, top
, width
, height
,
4987 /* Border width, depth, class, and visual. */
4994 bar
->x_window
= window
;
4996 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4998 XSETWINDOW (bar
->window
, w
);
5002 bar
->height
= height
;
5006 #if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
5007 bar
->last_seen_part
= scroll_bar_nowhere
;
5010 /* Add bar to its frame's list of scroll bars. */
5011 bar
->next
= FRAME_SCROLL_BARS (f
);
5013 XSETVECTOR (barobj
, bar
);
5014 fset_scroll_bars (f
, barobj
);
5015 if (!NILP (bar
->next
))
5016 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5018 /* Map the window/widget. */
5019 #ifdef USE_TOOLKIT_SCROLL_BARS
5022 xg_update_scrollbar_pos (f
, bar
->x_window
, top
,
5023 left
,width
, max (height
, 1));
5024 #else /* not USE_GTK */
5025 Widget scroll_bar
= SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
);
5026 XtConfigureWidget (scroll_bar
, left
, top
, width
, max (height
, 1), 0);
5027 XtMapWidget (scroll_bar
);
5028 #endif /* not USE_GTK */
5030 #else /* not USE_TOOLKIT_SCROLL_BARS */
5031 XMapRaised (FRAME_X_DISPLAY (f
), bar
->x_window
);
5032 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5039 #ifndef USE_TOOLKIT_SCROLL_BARS
5041 /* Draw BAR's handle in the proper position.
5043 If the handle is already drawn from START to END, don't bother
5044 redrawing it, unless REBUILD is non-zero; in that case, always
5045 redraw it. (REBUILD is handy for drawing the handle after expose
5048 Normally, we want to constrain the start and end of the handle to
5049 fit inside its rectangle, but if the user is dragging the scroll
5050 bar handle, we want to let them drag it down all the way, so that
5051 the bar's top is as far down as it goes; otherwise, there's no way
5052 to move to the very end of the buffer. */
5055 x_scroll_bar_set_handle (struct scroll_bar
*bar
, int start
, int end
, int rebuild
)
5057 bool dragging
= bar
->dragging
!= -1;
5058 Window w
= bar
->x_window
;
5059 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5060 GC gc
= f
->output_data
.x
->normal_gc
;
5062 /* If the display is already accurate, do nothing. */
5064 && start
== bar
->start
5071 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, bar
->width
);
5072 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, bar
->height
);
5073 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5075 /* Make sure the values are reasonable, and try to preserve
5076 the distance between start and end. */
5078 int length
= end
- start
;
5082 else if (start
> top_range
)
5084 end
= start
+ length
;
5088 else if (end
> top_range
&& ! dragging
)
5092 /* Store the adjusted setting in the scroll bar. */
5096 /* Clip the end position, just for display. */
5097 if (end
> top_range
)
5100 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
5101 below top positions, to make sure the handle is always at least
5102 that many pixels tall. */
5103 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5105 /* Draw the empty space above the handle. Note that we can't clear
5106 zero-height areas; that means "clear to end of window." */
5108 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5109 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5110 VERTICAL_SCROLL_BAR_TOP_BORDER
,
5111 inside_width
, start
);
5113 /* Change to proper foreground color if one is specified. */
5114 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5115 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5116 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5118 /* Draw the handle itself. */
5119 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5120 /* x, y, width, height */
5121 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5122 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
5123 inside_width
, end
- start
);
5125 /* Restore the foreground color of the GC if we changed it above. */
5126 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5127 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5128 FRAME_FOREGROUND_PIXEL (f
));
5130 /* Draw the empty space below the handle. Note that we can't
5131 clear zero-height areas; that means "clear to end of window." */
5132 if (end
< inside_height
)
5133 x_clear_area (FRAME_X_DISPLAY (f
), w
,
5134 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
5135 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
5136 inside_width
, inside_height
- end
);
5142 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5144 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5148 x_scroll_bar_remove (struct scroll_bar
*bar
)
5150 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5153 #ifdef USE_TOOLKIT_SCROLL_BARS
5155 xg_remove_scroll_bar (f
, bar
->x_window
);
5156 #else /* not USE_GTK */
5157 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
));
5158 #endif /* not USE_GTK */
5160 XDestroyWindow (FRAME_X_DISPLAY (f
), bar
->x_window
);
5163 /* Dissociate this scroll bar from its window. */
5164 wset_vertical_scroll_bar (XWINDOW (bar
->window
), Qnil
);
5170 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5171 that we are displaying PORTION characters out of a total of WHOLE
5172 characters, starting at POSITION. If WINDOW has no scroll bar,
5176 XTset_vertical_scroll_bar (struct window
*w
, int portion
, int whole
, int position
)
5178 struct frame
*f
= XFRAME (w
->frame
);
5180 struct scroll_bar
*bar
;
5181 int top
, height
, left
, width
;
5182 int window_y
, window_height
;
5184 /* Get window dimensions. */
5185 window_box (w
, ANY_AREA
, 0, &window_y
, 0, &window_height
);
5187 height
= window_height
;
5189 /* Compute the left edge and the width of the scroll bar area. */
5190 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
5191 width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
5193 /* Does the scroll bar exist yet? */
5194 if (NILP (w
->vertical_scroll_bar
))
5196 if (width
> 0 && height
> 0)
5199 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5200 left
, top
, width
, height
);
5204 bar
= x_scroll_bar_create (w
, top
, left
, width
, max (height
, 1));
5208 /* It may just need to be moved and resized. */
5209 unsigned int mask
= 0;
5211 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5215 if (left
!= bar
->left
)
5217 if (top
!= bar
->top
)
5219 if (width
!= bar
->width
)
5221 if (height
!= bar
->height
)
5224 #ifdef USE_TOOLKIT_SCROLL_BARS
5226 /* Move/size the scroll bar widget. */
5229 /* Since toolkit scroll bars are smaller than the space reserved
5230 for them on the frame, we have to clear "under" them. */
5231 if (width
> 0 && height
> 0)
5232 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5233 left
, top
, width
, height
);
5235 xg_update_scrollbar_pos (f
, bar
->x_window
, top
,
5236 left
, width
, max (height
, 1));
5237 #else /* not USE_GTK */
5238 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f
), bar
),
5239 left
, top
, width
, max (height
, 1), 0);
5240 #endif /* not USE_GTK */
5242 #else /* not USE_TOOLKIT_SCROLL_BARS */
5244 /* Move/size the scroll bar window. */
5253 XConfigureWindow (FRAME_X_DISPLAY (f
), bar
->x_window
,
5257 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5259 /* Remember new settings. */
5263 bar
->height
= height
;
5268 #ifdef USE_TOOLKIT_SCROLL_BARS
5269 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
5270 #else /* not USE_TOOLKIT_SCROLL_BARS */
5271 /* Set the scroll bar's current state, unless we're currently being
5273 if (bar
->dragging
== -1)
5275 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
5278 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
5281 int start
= ((double) position
* top_range
) / whole
;
5282 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
5283 x_scroll_bar_set_handle (bar
, start
, end
, 0);
5286 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5288 XSETVECTOR (barobj
, bar
);
5289 wset_vertical_scroll_bar (w
, barobj
);
5293 /* The following three hooks are used when we're doing a thorough
5294 redisplay of the frame. We don't explicitly know which scroll bars
5295 are going to be deleted, because keeping track of when windows go
5296 away is a real pain - "Can you say set-window-configuration, boys
5297 and girls?" Instead, we just assert at the beginning of redisplay
5298 that *all* scroll bars are to be removed, and then save a scroll bar
5299 from the fiery pit when we actually redisplay its window. */
5301 /* Arrange for all scroll bars on FRAME to be removed at the next call
5302 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5303 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5306 XTcondemn_scroll_bars (struct frame
*frame
)
5308 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5309 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5312 bar
= FRAME_SCROLL_BARS (frame
);
5313 fset_scroll_bars (frame
, XSCROLL_BAR (bar
)->next
);
5314 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5315 XSCROLL_BAR (bar
)->prev
= Qnil
;
5316 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5317 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5318 fset_condemned_scroll_bars (frame
, bar
);
5323 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5324 Note that WINDOW isn't necessarily condemned at all. */
5327 XTredeem_scroll_bar (struct window
*window
)
5329 struct scroll_bar
*bar
;
5333 /* We can't redeem this window's scroll bar if it doesn't have one. */
5334 if (NILP (window
->vertical_scroll_bar
))
5337 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5339 /* Unlink it from the condemned list. */
5340 f
= XFRAME (WINDOW_FRAME (window
));
5341 if (NILP (bar
->prev
))
5343 /* If the prev pointer is nil, it must be the first in one of
5345 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5346 /* It's not condemned. Everything's fine. */
5348 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5349 window
->vertical_scroll_bar
))
5350 fset_condemned_scroll_bars (f
, bar
->next
);
5352 /* If its prev pointer is nil, it must be at the front of
5353 one or the other! */
5357 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5359 if (! NILP (bar
->next
))
5360 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5362 bar
->next
= FRAME_SCROLL_BARS (f
);
5364 XSETVECTOR (barobj
, bar
);
5365 fset_scroll_bars (f
, barobj
);
5366 if (! NILP (bar
->next
))
5367 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5370 /* Remove all scroll bars on FRAME that haven't been saved since the
5371 last call to `*condemn_scroll_bars_hook'. */
5374 XTjudge_scroll_bars (struct frame
*f
)
5376 Lisp_Object bar
, next
;
5378 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5380 /* Clear out the condemned list now so we won't try to process any
5381 more events on the hapless scroll bars. */
5382 fset_condemned_scroll_bars (f
, Qnil
);
5384 for (; ! NILP (bar
); bar
= next
)
5386 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5388 x_scroll_bar_remove (b
);
5391 b
->next
= b
->prev
= Qnil
;
5394 /* Now there should be no references to the condemned scroll bars,
5395 and they should get garbage-collected. */
5399 #ifndef USE_TOOLKIT_SCROLL_BARS
5400 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5401 is a no-op when using toolkit scroll bars.
5403 This may be called from a signal handler, so we have to ignore GC
5407 x_scroll_bar_expose (struct scroll_bar
*bar
, const XEvent
*event
)
5409 Window w
= bar
->x_window
;
5410 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5411 GC gc
= f
->output_data
.x
->normal_gc
;
5415 x_scroll_bar_set_handle (bar
, bar
->start
, bar
->end
, 1);
5417 /* Switch to scroll bar foreground color. */
5418 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5419 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5420 f
->output_data
.x
->scroll_bar_foreground_pixel
);
5422 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5423 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
5424 /* x, y, width, height */
5425 0, 0, bar
->width
- 1, bar
->height
- 1);
5427 /* Restore the foreground color of the GC if we changed it above. */
5428 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
5429 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
5430 FRAME_FOREGROUND_PIXEL (f
));
5435 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5437 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5438 is set to something other than NO_EVENT, it is enqueued.
5440 This may be called from a signal handler, so we have to ignore GC
5445 x_scroll_bar_handle_click (struct scroll_bar
*bar
,
5446 const XEvent
*event
,
5447 struct input_event
*emacs_event
)
5449 if (! WINDOWP (bar
->window
))
5452 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
5453 emacs_event
->code
= event
->xbutton
.button
- Button1
;
5454 emacs_event
->modifiers
5455 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
5456 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
5457 event
->xbutton
.state
)
5458 | (event
->type
== ButtonRelease
5461 emacs_event
->frame_or_window
= bar
->window
;
5462 emacs_event
->arg
= Qnil
;
5463 emacs_event
->timestamp
= event
->xbutton
.time
;
5466 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5467 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
5470 if (y
> top_range
) y
= top_range
;
5473 emacs_event
->part
= scroll_bar_above_handle
;
5474 else if (y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5475 emacs_event
->part
= scroll_bar_handle
;
5477 emacs_event
->part
= scroll_bar_below_handle
;
5479 #ifndef USE_TOOLKIT_SCROLL_BARS
5480 /* If the user has released the handle, set it to its final position. */
5481 if (event
->type
== ButtonRelease
&& bar
->dragging
!= -1)
5483 int new_start
= y
- bar
->dragging
;
5484 int new_end
= new_start
+ bar
->end
- bar
->start
;
5486 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5491 XSETINT (emacs_event
->x
, y
);
5492 XSETINT (emacs_event
->y
, top_range
);
5496 #ifndef USE_TOOLKIT_SCROLL_BARS
5498 /* Handle some mouse motion while someone is dragging the scroll bar.
5500 This may be called from a signal handler, so we have to ignore GC
5504 x_scroll_bar_note_movement (struct scroll_bar
*bar
,
5505 const XMotionEvent
*event
)
5507 struct frame
*f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5508 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
5510 dpyinfo
->last_mouse_movement_time
= event
->time
;
5511 dpyinfo
->last_mouse_scroll_bar
= bar
;
5514 /* If we're dragging the bar, display it. */
5515 if (bar
->dragging
!= -1)
5517 /* Where should the handle be now? */
5518 int new_start
= event
->y
- bar
->dragging
;
5520 if (new_start
!= bar
->start
)
5522 int new_end
= new_start
+ bar
->end
- bar
->start
;
5524 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5529 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5531 /* Return information to the user about the current position of the mouse
5532 on the scroll bar. */
5535 x_scroll_bar_report_motion (struct frame
**fp
, Lisp_Object
*bar_window
,
5536 enum scroll_bar_part
*part
, Lisp_Object
*x
,
5537 Lisp_Object
*y
, Time
*timestamp
)
5539 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (*fp
);
5540 struct scroll_bar
*bar
= dpyinfo
->last_mouse_scroll_bar
;
5541 Window w
= bar
->x_window
;
5542 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5544 Window dummy_window
;
5546 unsigned int dummy_mask
;
5550 /* Get the mouse's position relative to the scroll bar window, and
5552 if (XQueryPointer (FRAME_X_DISPLAY (f
), w
,
5554 /* Root, child, root x and root y. */
5555 &dummy_window
, &dummy_window
,
5556 &dummy_coord
, &dummy_coord
,
5558 /* Position relative to scroll bar. */
5561 /* Mouse buttons and modifier keys. */
5564 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, bar
->height
);
5566 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5568 if (bar
->dragging
!= -1)
5569 win_y
-= bar
->dragging
;
5573 if (win_y
> top_range
)
5577 *bar_window
= bar
->window
;
5579 if (bar
->dragging
!= -1)
5580 *part
= scroll_bar_handle
;
5581 else if (win_y
< bar
->start
)
5582 *part
= scroll_bar_above_handle
;
5583 else if (win_y
< bar
->end
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5584 *part
= scroll_bar_handle
;
5586 *part
= scroll_bar_below_handle
;
5588 XSETINT (*x
, win_y
);
5589 XSETINT (*y
, top_range
);
5592 dpyinfo
->last_mouse_scroll_bar
= NULL
;
5593 *timestamp
= dpyinfo
->last_mouse_movement_time
;
5600 /* The screen has been cleared so we may have changed foreground or
5601 background colors, and the scroll bars may need to be redrawn.
5602 Clear out the scroll bars, and ask for expose events, so we can
5606 x_scroll_bar_clear (struct frame
*f
)
5608 #ifndef USE_TOOLKIT_SCROLL_BARS
5611 /* We can have scroll bars even if this is 0,
5612 if we just turned off scroll bar mode.
5613 But in that case we should not clear them. */
5614 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5615 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
5616 bar
= XSCROLL_BAR (bar
)->next
)
5617 XClearArea (FRAME_X_DISPLAY (f
),
5618 XSCROLL_BAR (bar
)->x_window
,
5620 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5623 #ifdef ENABLE_CHECKING
5625 /* Record the last 100 characters stored
5626 to help debug the loss-of-chars-during-GC problem. */
5628 static int temp_index
;
5629 static short temp_buffer
[100];
5631 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5632 if (temp_index == ARRAYELTS (temp_buffer)) \
5634 temp_buffer[temp_index++] = (keysym)
5636 #else /* not ENABLE_CHECKING */
5638 #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
5640 #endif /* ENABLE_CHECKING */
5642 /* Set this to nonzero to fake an "X I/O error"
5643 on a particular display. */
5645 static struct x_display_info
*XTread_socket_fake_io_error
;
5647 /* When we find no input here, we occasionally do a no-op command
5648 to verify that the X server is still running and we can still talk with it.
5649 We try all the open displays, one by one.
5650 This variable is used for cycling thru the displays. */
5652 static struct x_display_info
*next_noop_dpyinfo
;
5661 /* Filter events for the current X input method.
5662 DPYINFO is the display this event is for.
5663 EVENT is the X event to filter.
5665 Returns non-zero if the event was filtered, caller shall not process
5667 Returns zero if event is wasn't filtered. */
5671 x_filter_event (struct x_display_info
*dpyinfo
, XEvent
*event
)
5673 /* XFilterEvent returns non-zero if the input method has
5674 consumed the event. We pass the frame's X window to
5675 XFilterEvent because that's the one for which the IC
5678 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
5679 event
->xclient
.window
);
5681 return XFilterEvent (event
, f1
? FRAME_X_WINDOW (f1
) : None
);
5686 static int current_count
;
5687 static int current_finish
;
5688 static struct input_event
*current_hold_quit
;
5690 /* This is the filter function invoked by the GTK event loop.
5691 It is invoked before the XEvent is translated to a GdkEvent,
5692 so we have a chance to act on the event before GTK. */
5693 static GdkFilterReturn
5694 event_handler_gdk (GdkXEvent
*gxev
, GdkEvent
*ev
, gpointer data
)
5696 XEvent
*xev
= (XEvent
*) gxev
;
5699 if (current_count
>= 0)
5701 struct x_display_info
*dpyinfo
;
5703 dpyinfo
= x_display_info_for_display (xev
->xany
.display
);
5706 /* Filter events for the current X input method.
5707 GTK calls XFilterEvent but not for key press and release,
5708 so we do it here. */
5709 if ((xev
->type
== KeyPress
|| xev
->type
== KeyRelease
)
5711 && x_filter_event (dpyinfo
, xev
))
5714 return GDK_FILTER_REMOVE
;
5719 current_finish
= X_EVENT_NORMAL
;
5722 += handle_one_xevent (dpyinfo
, xev
, ¤t_finish
,
5726 current_finish
= x_dispatch_event (xev
, xev
->xany
.display
);
5730 if (current_finish
== X_EVENT_GOTO_OUT
|| current_finish
== X_EVENT_DROP
)
5731 return GDK_FILTER_REMOVE
;
5733 return GDK_FILTER_CONTINUE
;
5735 #endif /* USE_GTK */
5738 static void xembed_send_message (struct frame
*f
, Time
,
5739 enum xembed_message
,
5740 long detail
, long data1
, long data2
);
5742 /* Handles the XEvent EVENT on display DPYINFO.
5744 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5745 *FINISH is zero if caller should continue reading events.
5746 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5747 *EVENT is unchanged unless we're processing KeyPress event.
5749 We return the number of characters stored into the buffer. */
5752 handle_one_xevent (struct x_display_info
*dpyinfo
,
5753 const XEvent
*event
,
5754 int *finish
, struct input_event
*hold_quit
)
5757 struct input_event ie
;
5758 struct selection_input_event sie
;
5762 ptrdiff_t nbytes
= 0;
5763 struct frame
*any
, *f
= NULL
;
5764 struct coding_system coding
;
5765 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
5766 /* This holds the state XLookupString needs to implement dead keys
5767 and other tricks known as "compose processing". _X Window System_
5768 says that a portable program can't use this, but Stephen Gildea assures
5769 me that letting the compiler initialize it to zeros will work okay. */
5770 static XComposeStatus compose_status
;
5774 *finish
= X_EVENT_NORMAL
;
5776 EVENT_INIT (inev
.ie
);
5777 inev
.ie
.kind
= NO_EVENT
;
5780 any
= x_any_window_to_frame (dpyinfo
, event
->xany
.window
);
5782 if (any
&& any
->wait_event_type
== event
->type
)
5783 any
->wait_event_type
= 0; /* Indicates we got it. */
5785 switch (event
->type
)
5789 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_protocols
5790 && event
->xclient
.format
== 32)
5792 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_take_focus
)
5794 /* Use the value returned by x_any_window_to_frame
5795 because this could be the shell widget window
5796 if the frame has no title bar. */
5799 /* Not quite sure this is needed -pd */
5800 if (f
&& FRAME_XIC (f
))
5801 XSetICFocus (FRAME_XIC (f
));
5803 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5804 instructs the WM to set the input focus automatically for
5805 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5806 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5807 it has set the focus. So, XSetInputFocus below is not
5810 The call to XSetInputFocus below has also caused trouble. In
5811 cases where the XSetInputFocus done by the WM and the one
5812 below are temporally close (on a fast machine), the call
5813 below can generate additional FocusIn events which confuse
5816 /* Since we set WM_TAKE_FOCUS, we must call
5817 XSetInputFocus explicitly. But not if f is null,
5818 since that might be an event for a deleted frame. */
5821 Display
*d
= event
->xclient
.display
;
5822 /* Catch and ignore errors, in case window has been
5823 iconified by a window manager such as GWM. */
5825 XSetInputFocus (d
, event
->xclient
.window
,
5826 /* The ICCCM says this is
5827 the only valid choice. */
5829 event
->xclient
.data
.l
[1]);
5830 /* This is needed to detect the error
5831 if there is an error. */
5833 x_uncatch_errors ();
5835 /* Not certain about handling scroll bars here */
5840 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_save_yourself
)
5842 /* Save state modify the WM_COMMAND property to
5843 something which can reinstate us. This notifies
5844 the session manager, who's looking for such a
5845 PropertyNotify. Can restart processing when
5846 a keyboard or mouse event arrives. */
5847 /* If we have a session manager, don't set this.
5848 KDE will then start two Emacsen, one for the
5849 session manager and one for this. */
5851 if (! x_session_have_connection ())
5854 f
= x_top_window_to_frame (dpyinfo
,
5855 event
->xclient
.window
);
5856 /* This is just so we only give real data once
5857 for a single Emacs process. */
5858 if (f
== SELECTED_FRAME ())
5859 XSetCommand (FRAME_X_DISPLAY (f
),
5860 event
->xclient
.window
,
5861 initial_argv
, initial_argc
);
5863 XSetCommand (FRAME_X_DISPLAY (f
),
5864 event
->xclient
.window
,
5870 if (event
->xclient
.data
.l
[0] == dpyinfo
->Xatom_wm_delete_window
)
5874 goto OTHER
; /* May be a dialog that is to be removed */
5876 inev
.ie
.kind
= DELETE_WINDOW_EVENT
;
5877 XSETFRAME (inev
.ie
.frame_or_window
, f
);
5884 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_configure_denied
)
5887 if (event
->xclient
.message_type
== dpyinfo
->Xatom_wm_window_moved
)
5890 f
= x_window_to_frame (dpyinfo
, event
->xclient
.window
);
5892 new_x
= event
->xclient
.data
.s
[0];
5893 new_y
= event
->xclient
.data
.s
[1];
5897 f
->left_pos
= new_x
;
5904 if (event
->xclient
.message_type
== dpyinfo
->Xatom_editres
)
5908 _XEditResCheckMessages (f
->output_data
.x
->widget
,
5909 NULL
, (XEvent
*) event
, NULL
);
5912 #endif /* HACK_EDITRES */
5914 if (event
->xclient
.message_type
== dpyinfo
->Xatom_DONE
5915 || event
->xclient
.message_type
== dpyinfo
->Xatom_PAGE
)
5917 /* Ghostview job completed. Kill it. We could
5918 reply with "Next" if we received "Page", but we
5919 currently never do because we are interested in
5920 images, only, which should have 1 page. */
5921 Pixmap pixmap
= (Pixmap
) event
->xclient
.data
.l
[1];
5922 f
= x_window_to_frame (dpyinfo
, event
->xclient
.window
);
5925 x_kill_gs_process (pixmap
, f
);
5926 expose_frame (f
, 0, 0, 0, 0);
5930 #ifdef USE_TOOLKIT_SCROLL_BARS
5931 /* Scroll bar callbacks send a ClientMessage from which
5932 we construct an input_event. */
5933 if (event
->xclient
.message_type
== dpyinfo
->Xatom_Scrollbar
)
5935 x_scroll_bar_to_input_event (event
, &inev
.ie
);
5936 *finish
= X_EVENT_GOTO_OUT
;
5939 #endif /* USE_TOOLKIT_SCROLL_BARS */
5941 /* XEmbed messages from the embedder (if any). */
5942 if (event
->xclient
.message_type
== dpyinfo
->Xatom_XEMBED
)
5944 enum xembed_message msg
= event
->xclient
.data
.l
[1];
5945 if (msg
== XEMBED_FOCUS_IN
|| msg
== XEMBED_FOCUS_OUT
)
5946 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
5948 *finish
= X_EVENT_GOTO_OUT
;
5952 xft_settings_event (dpyinfo
, event
);
5957 if (x_handle_dnd_message (f
, &event
->xclient
, dpyinfo
, &inev
.ie
))
5958 *finish
= X_EVENT_DROP
;
5962 case SelectionNotify
:
5963 dpyinfo
->last_user_time
= event
->xselection
.time
;
5964 #ifdef USE_X_TOOLKIT
5965 if (! x_window_to_frame (dpyinfo
, event
->xselection
.requestor
))
5967 #endif /* not USE_X_TOOLKIT */
5968 x_handle_selection_notify (&event
->xselection
);
5971 case SelectionClear
: /* Someone has grabbed ownership. */
5972 dpyinfo
->last_user_time
= event
->xselectionclear
.time
;
5973 #ifdef USE_X_TOOLKIT
5974 if (! x_window_to_frame (dpyinfo
, event
->xselectionclear
.window
))
5976 #endif /* USE_X_TOOLKIT */
5978 const XSelectionClearEvent
*eventp
= &event
->xselectionclear
;
5980 inev
.ie
.kind
= SELECTION_CLEAR_EVENT
;
5981 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
5982 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
5983 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
5987 case SelectionRequest
: /* Someone wants our selection. */
5988 dpyinfo
->last_user_time
= event
->xselectionrequest
.time
;
5989 #ifdef USE_X_TOOLKIT
5990 if (!x_window_to_frame (dpyinfo
, event
->xselectionrequest
.owner
))
5992 #endif /* USE_X_TOOLKIT */
5994 const XSelectionRequestEvent
*eventp
= &event
->xselectionrequest
;
5996 inev
.ie
.kind
= SELECTION_REQUEST_EVENT
;
5997 SELECTION_EVENT_DISPLAY (&inev
.sie
) = eventp
->display
;
5998 SELECTION_EVENT_REQUESTOR (&inev
.sie
) = eventp
->requestor
;
5999 SELECTION_EVENT_SELECTION (&inev
.sie
) = eventp
->selection
;
6000 SELECTION_EVENT_TARGET (&inev
.sie
) = eventp
->target
;
6001 SELECTION_EVENT_PROPERTY (&inev
.sie
) = eventp
->property
;
6002 SELECTION_EVENT_TIME (&inev
.sie
) = eventp
->time
;
6006 case PropertyNotify
:
6007 dpyinfo
->last_user_time
= event
->xproperty
.time
;
6008 f
= x_top_window_to_frame (dpyinfo
, event
->xproperty
.window
);
6009 if (f
&& event
->xproperty
.atom
== dpyinfo
->Xatom_net_wm_state
)
6010 if (x_handle_net_wm_state (f
, &event
->xproperty
)
6011 && FRAME_ICONIFIED_P (f
)
6012 && f
->output_data
.x
->net_wm_state_hidden_seen
)
6014 /* Gnome shell does not iconify us when C-z is pressed.
6015 It hides the frame. So if our state says we aren't
6016 hidden anymore, treat it as deiconified. */
6017 SET_FRAME_VISIBLE (f
, 1);
6018 SET_FRAME_ICONIFIED (f
, 0);
6019 f
->output_data
.x
->has_been_visible
= 1;
6020 f
->output_data
.x
->net_wm_state_hidden_seen
= 0;
6021 inev
.ie
.kind
= DEICONIFY_EVENT
;
6022 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6025 x_handle_property_notify (&event
->xproperty
);
6026 xft_settings_event (dpyinfo
, event
);
6029 case ReparentNotify
:
6030 f
= x_top_window_to_frame (dpyinfo
, event
->xreparent
.window
);
6033 f
->output_data
.x
->parent_desc
= event
->xreparent
.parent
;
6034 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6036 /* Perhaps reparented due to a WM restart. Reset this. */
6037 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_UNKNOWN
;
6038 FRAME_DISPLAY_INFO (f
)->net_supported_window
= 0;
6040 x_set_frame_alpha (f
);
6045 f
= x_window_to_frame (dpyinfo
, event
->xexpose
.window
);
6048 if (!FRAME_VISIBLE_P (f
))
6050 SET_FRAME_VISIBLE (f
, 1);
6051 SET_FRAME_ICONIFIED (f
, 0);
6052 f
->output_data
.x
->has_been_visible
= 1;
6053 SET_FRAME_GARBAGED (f
);
6058 /* This seems to be needed for GTK 2.6 and later, see
6059 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
6060 x_clear_area (event
->xexpose
.display
,
6061 event
->xexpose
.window
,
6062 event
->xexpose
.x
, event
->xexpose
.y
,
6063 event
->xexpose
.width
, event
->xexpose
.height
);
6065 expose_frame (f
, event
->xexpose
.x
, event
->xexpose
.y
,
6066 event
->xexpose
.width
, event
->xexpose
.height
);
6071 #ifndef USE_TOOLKIT_SCROLL_BARS
6072 struct scroll_bar
*bar
;
6074 #if defined USE_LUCID
6075 /* Submenus of the Lucid menu bar aren't widgets
6076 themselves, so there's no way to dispatch events
6077 to them. Recognize this case separately. */
6079 Widget widget
= x_window_to_menu_bar (event
->xexpose
.window
);
6081 xlwmenu_redisplay (widget
);
6083 #endif /* USE_LUCID */
6085 #ifdef USE_TOOLKIT_SCROLL_BARS
6086 /* Dispatch event to the widget. */
6088 #else /* not USE_TOOLKIT_SCROLL_BARS */
6089 bar
= x_window_to_scroll_bar (event
->xexpose
.display
,
6090 event
->xexpose
.window
);
6093 x_scroll_bar_expose (bar
, event
);
6094 #ifdef USE_X_TOOLKIT
6097 #endif /* USE_X_TOOLKIT */
6098 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6102 case GraphicsExpose
: /* This occurs when an XCopyArea's
6103 source area was obscured or not
6105 f
= x_window_to_frame (dpyinfo
, event
->xgraphicsexpose
.drawable
);
6107 expose_frame (f
, event
->xgraphicsexpose
.x
,
6108 event
->xgraphicsexpose
.y
,
6109 event
->xgraphicsexpose
.width
,
6110 event
->xgraphicsexpose
.height
);
6111 #ifdef USE_X_TOOLKIT
6114 #endif /* USE_X_TOOLKIT */
6117 case NoExpose
: /* This occurs when an XCopyArea's
6118 source area was completely
6123 /* Redo the mouse-highlight after the tooltip has gone. */
6124 if (event
->xunmap
.window
== tip_window
)
6127 x_redo_mouse_highlight (dpyinfo
);
6130 f
= x_top_window_to_frame (dpyinfo
, event
->xunmap
.window
);
6131 if (f
) /* F may no longer exist if
6132 the frame was deleted. */
6134 bool visible
= FRAME_VISIBLE_P (f
);
6135 /* While a frame is unmapped, display generation is
6136 disabled; you don't want to spend time updating a
6137 display that won't ever be seen. */
6138 SET_FRAME_VISIBLE (f
, 0);
6139 /* We can't distinguish, from the event, whether the window
6140 has become iconified or invisible. So assume, if it
6141 was previously visible, than now it is iconified.
6142 But x_make_frame_invisible clears both
6143 the visible flag and the iconified flag;
6144 and that way, we know the window is not iconified now. */
6145 if (visible
|| FRAME_ICONIFIED_P (f
))
6147 SET_FRAME_ICONIFIED (f
, 1);
6148 inev
.ie
.kind
= ICONIFY_EVENT
;
6149 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6155 if (event
->xmap
.window
== tip_window
)
6156 /* The tooltip has been drawn already. Avoid
6157 the SET_FRAME_GARBAGED below. */
6160 /* We use x_top_window_to_frame because map events can
6161 come for sub-windows and they don't mean that the
6162 frame is visible. */
6163 f
= x_top_window_to_frame (dpyinfo
, event
->xmap
.window
);
6166 bool iconified
= FRAME_ICONIFIED_P (f
);
6168 /* Check if fullscreen was specified before we where mapped the
6169 first time, i.e. from the command line. */
6170 if (!f
->output_data
.x
->has_been_visible
)
6171 x_check_fullscreen (f
);
6173 SET_FRAME_VISIBLE (f
, 1);
6174 SET_FRAME_ICONIFIED (f
, 0);
6175 f
->output_data
.x
->has_been_visible
= 1;
6179 inev
.ie
.kind
= DEICONIFY_EVENT
;
6180 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6182 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6183 /* Force a redisplay sooner or later to update the
6184 frame titles in case this is the second frame. */
6185 record_asynch_buffer_change ();
6188 xg_frame_resized (f
, -1, -1);
6195 dpyinfo
->last_user_time
= event
->xkey
.time
;
6196 ignore_next_mouse_click_timeout
= 0;
6198 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6199 /* Dispatch KeyPress events when in menu. */
6200 if (popup_activated ())
6206 #if ! defined (USE_GTK)
6207 /* If mouse-highlight is an integer, input clears out
6208 mouse highlighting. */
6209 if (!hlinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
6211 || !EQ (f
->tool_bar_window
, hlinfo
->mouse_face_window
)))
6213 clear_mouse_face (hlinfo
);
6214 hlinfo
->mouse_face_hidden
= 1;
6218 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6221 /* Scroll bars consume key events, but we want
6222 the keys to go to the scroll bar's frame. */
6223 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
6224 event
->xkey
.window
);
6225 if (widget
&& XmIsScrollBar (widget
))
6227 widget
= XtParent (widget
);
6228 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
6231 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6235 KeySym keysym
, orig_keysym
;
6236 /* al%imercury@uunet.uu.net says that making this 81
6237 instead of 80 fixed a bug whereby meta chars made
6240 It seems that some version of XmbLookupString has
6241 a bug of not returning XBufferOverflow in
6242 status_return even if the input is too long to
6243 fit in 81 bytes. So, we must prepare sufficient
6244 bytes for copy_buffer. 513 bytes (256 chars for
6245 two-byte character set) seems to be a fairly good
6246 approximation. -- 2000.8.10 handa@etl.go.jp */
6247 unsigned char copy_buffer
[513];
6248 unsigned char *copy_bufptr
= copy_buffer
;
6249 int copy_bufsiz
= sizeof (copy_buffer
);
6251 Lisp_Object coding_system
= Qlatin_1
;
6253 /* Event will be modified. */
6254 XKeyEvent xkey
= event
->xkey
;
6257 /* Don't pass keys to GTK. A Tab will shift focus to the
6258 tool bar in GTK 2.4. Keys will still go to menus and
6259 dialogs because in that case popup_activated is nonzero
6261 *finish
= X_EVENT_DROP
;
6264 xkey
.state
|= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f
),
6265 extra_keyboard_modifiers
);
6266 modifiers
= xkey
.state
;
6268 /* This will have to go some day... */
6270 /* make_lispy_event turns chars into control chars.
6271 Don't do it here because XLookupString is too eager. */
6272 xkey
.state
&= ~ControlMask
;
6273 xkey
.state
&= ~(dpyinfo
->meta_mod_mask
6274 | dpyinfo
->super_mod_mask
6275 | dpyinfo
->hyper_mod_mask
6276 | dpyinfo
->alt_mod_mask
);
6278 /* In case Meta is ComposeCharacter,
6279 clear its status. According to Markus Ehrnsperger
6280 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6281 this enables ComposeCharacter to work whether or
6282 not it is combined with Meta. */
6283 if (modifiers
& dpyinfo
->meta_mod_mask
)
6284 memset (&compose_status
, 0, sizeof (compose_status
));
6289 Status status_return
;
6291 coding_system
= Vlocale_coding_system
;
6292 nbytes
= XmbLookupString (FRAME_XIC (f
),
6293 &xkey
, (char *) copy_bufptr
,
6294 copy_bufsiz
, &keysym
,
6296 if (status_return
== XBufferOverflow
)
6298 copy_bufsiz
= nbytes
+ 1;
6299 copy_bufptr
= alloca (copy_bufsiz
);
6300 nbytes
= XmbLookupString (FRAME_XIC (f
),
6301 &xkey
, (char *) copy_bufptr
,
6302 copy_bufsiz
, &keysym
,
6305 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6306 if (status_return
== XLookupNone
)
6308 else if (status_return
== XLookupChars
)
6313 else if (status_return
!= XLookupKeySym
6314 && status_return
!= XLookupBoth
)
6318 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
6319 copy_bufsiz
, &keysym
,
6322 nbytes
= XLookupString (&xkey
, (char *) copy_bufptr
,
6323 copy_bufsiz
, &keysym
,
6327 /* If not using XIM/XIC, and a compose sequence is in progress,
6328 we break here. Otherwise, chars_matched is always 0. */
6329 if (compose_status
.chars_matched
> 0 && nbytes
== 0)
6332 memset (&compose_status
, 0, sizeof (compose_status
));
6333 orig_keysym
= keysym
;
6335 /* Common for all keysym input events. */
6336 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6338 = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f
), modifiers
);
6339 inev
.ie
.timestamp
= xkey
.time
;
6341 /* First deal with keysyms which have defined
6342 translations to characters. */
6343 if (keysym
>= 32 && keysym
< 128)
6344 /* Avoid explicitly decoding each ASCII character. */
6346 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6347 inev
.ie
.code
= keysym
;
6351 /* Keysyms directly mapped to Unicode characters. */
6352 if (keysym
>= 0x01000000 && keysym
<= 0x0110FFFF)
6354 if (keysym
< 0x01000080)
6355 inev
.ie
.kind
= ASCII_KEYSTROKE_EVENT
;
6357 inev
.ie
.kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
6358 inev
.ie
.code
= keysym
& 0xFFFFFF;
6362 /* Now non-ASCII. */
6363 if (HASH_TABLE_P (Vx_keysym_table
)
6364 && (c
= Fgethash (make_number (keysym
),
6369 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (XFASTINT (c
))
6370 ? ASCII_KEYSTROKE_EVENT
6371 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6372 inev
.ie
.code
= XFASTINT (c
);
6376 /* Random non-modifier sorts of keysyms. */
6377 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
6378 || keysym
== XK_Delete
6379 #ifdef XK_ISO_Left_Tab
6380 || (keysym
>= XK_ISO_Left_Tab
6381 && keysym
<= XK_ISO_Enter
)
6383 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
6384 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
6386 /* This recognizes the "extended function
6387 keys". It seems there's no cleaner way.
6388 Test IsModifierKey to avoid handling
6389 mode_switch incorrectly. */
6390 || (XK_Select
<= keysym
&& keysym
< XK_KP_Space
)
6392 #ifdef XK_dead_circumflex
6393 || orig_keysym
== XK_dead_circumflex
6395 #ifdef XK_dead_grave
6396 || orig_keysym
== XK_dead_grave
6398 #ifdef XK_dead_tilde
6399 || orig_keysym
== XK_dead_tilde
6401 #ifdef XK_dead_diaeresis
6402 || orig_keysym
== XK_dead_diaeresis
6404 #ifdef XK_dead_macron
6405 || orig_keysym
== XK_dead_macron
6407 #ifdef XK_dead_degree
6408 || orig_keysym
== XK_dead_degree
6410 #ifdef XK_dead_acute
6411 || orig_keysym
== XK_dead_acute
6413 #ifdef XK_dead_cedilla
6414 || orig_keysym
== XK_dead_cedilla
6416 #ifdef XK_dead_breve
6417 || orig_keysym
== XK_dead_breve
6419 #ifdef XK_dead_ogonek
6420 || orig_keysym
== XK_dead_ogonek
6422 #ifdef XK_dead_caron
6423 || orig_keysym
== XK_dead_caron
6425 #ifdef XK_dead_doubleacute
6426 || orig_keysym
== XK_dead_doubleacute
6428 #ifdef XK_dead_abovedot
6429 || orig_keysym
== XK_dead_abovedot
6431 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
6432 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
6433 /* Any "vendor-specific" key is ok. */
6434 || (orig_keysym
& (1 << 28))
6435 || (keysym
!= NoSymbol
&& nbytes
== 0))
6436 && ! (IsModifierKey (orig_keysym
)
6437 /* The symbols from XK_ISO_Lock
6438 to XK_ISO_Last_Group_Lock
6439 don't have real modifiers but
6440 should be treated similarly to
6441 Mode_switch by Emacs. */
6442 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6443 || (XK_ISO_Lock
<= orig_keysym
6444 && orig_keysym
<= XK_ISO_Last_Group_Lock
)
6448 STORE_KEYSYM_FOR_DEBUG (keysym
);
6449 /* make_lispy_event will convert this to a symbolic
6451 inev
.ie
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
6452 inev
.ie
.code
= keysym
;
6456 { /* Raw bytes, not keysym. */
6460 for (i
= 0, nchars
= 0; i
< nbytes
; i
++)
6462 if (ASCII_BYTE_P (copy_bufptr
[i
]))
6464 STORE_KEYSYM_FOR_DEBUG (copy_bufptr
[i
]);
6467 if (nchars
< nbytes
)
6469 /* Decode the input data. */
6471 /* The input should be decoded with `coding_system'
6472 which depends on which X*LookupString function
6473 we used just above and the locale. */
6474 setup_coding_system (coding_system
, &coding
);
6475 coding
.src_multibyte
= 0;
6476 coding
.dst_multibyte
= 1;
6477 /* The input is converted to events, thus we can't
6478 handle composition. Anyway, there's no XIM that
6479 gives us composition information. */
6480 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
6482 SAFE_NALLOCA (coding
.destination
, MAX_MULTIBYTE_LENGTH
,
6484 coding
.dst_bytes
= MAX_MULTIBYTE_LENGTH
* nbytes
;
6485 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6486 decode_coding_c_string (&coding
, copy_bufptr
, nbytes
, Qnil
);
6487 nbytes
= coding
.produced
;
6488 nchars
= coding
.produced_char
;
6489 copy_bufptr
= coding
.destination
;
6492 /* Convert the input data to a sequence of
6493 character events. */
6494 for (i
= 0; i
< nbytes
; i
+= len
)
6497 if (nchars
== nbytes
)
6498 ch
= copy_bufptr
[i
], len
= 1;
6500 ch
= STRING_CHAR_AND_LENGTH (copy_bufptr
+ i
, len
);
6501 inev
.ie
.kind
= (SINGLE_BYTE_CHAR_P (ch
)
6502 ? ASCII_KEYSTROKE_EVENT
6503 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
);
6505 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
6510 inev
.ie
.kind
= NO_EVENT
; /* Already stored above. */
6512 if (keysym
== NoSymbol
)
6515 /* FIXME: check side effects and remove this. */
6516 ((XEvent
*) event
)->xkey
= xkey
;
6520 /* Don't dispatch this event since XtDispatchEvent calls
6521 XFilterEvent, and two calls in a row may freeze the
6529 dpyinfo
->last_user_time
= event
->xkey
.time
;
6531 /* Don't dispatch this event since XtDispatchEvent calls
6532 XFilterEvent, and two calls in a row may freeze the
6540 dpyinfo
->last_user_time
= event
->xcrossing
.time
;
6541 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
6545 if (f
&& x_mouse_click_focus_ignore_position
)
6546 ignore_next_mouse_click_timeout
= event
->xmotion
.time
+ 200;
6548 /* EnterNotify counts as mouse movement,
6549 so update things that depend on mouse position. */
6550 if (f
&& !f
->output_data
.x
->hourglass_p
)
6551 note_mouse_movement (f
, &event
->xmotion
);
6553 /* We may get an EnterNotify on the buttons in the toolbar. In that
6554 case we moved out of any highlighted area and need to note this. */
6555 if (!f
&& dpyinfo
->last_mouse_glyph_frame
)
6556 note_mouse_movement (dpyinfo
->last_mouse_glyph_frame
, &event
->xmotion
);
6561 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
6565 dpyinfo
->last_user_time
= event
->xcrossing
.time
;
6566 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
6568 f
= x_top_window_to_frame (dpyinfo
, event
->xcrossing
.window
);
6571 if (f
== hlinfo
->mouse_face_mouse_frame
)
6573 /* If we move outside the frame, then we're
6574 certainly no longer on any text in the frame. */
6575 clear_mouse_face (hlinfo
);
6576 hlinfo
->mouse_face_mouse_frame
= 0;
6579 /* Generate a nil HELP_EVENT to cancel a help-echo.
6580 Do it only if there's something to cancel.
6581 Otherwise, the startup message is cleared when
6582 the mouse leaves the frame. */
6583 if (any_help_event_p
)
6587 /* See comment in EnterNotify above */
6588 else if (dpyinfo
->last_mouse_glyph_frame
)
6589 note_mouse_movement (dpyinfo
->last_mouse_glyph_frame
, &event
->xmotion
);
6594 x_detect_focus_change (dpyinfo
, any
, event
, &inev
.ie
);
6599 dpyinfo
->last_user_time
= event
->xmotion
.time
;
6600 previous_help_echo_string
= help_echo_string
;
6601 help_echo_string
= Qnil
;
6603 f
= (x_mouse_grabbed (dpyinfo
) ? dpyinfo
->last_mouse_frame
6604 : x_window_to_frame (dpyinfo
, event
->xmotion
.window
));
6606 if (hlinfo
->mouse_face_hidden
)
6608 hlinfo
->mouse_face_hidden
= 0;
6609 clear_mouse_face (hlinfo
);
6613 if (f
&& xg_event_is_for_scrollbar (f
, event
))
6619 /* Generate SELECT_WINDOW_EVENTs when needed.
6620 Don't let popup menus influence things (bug#1261). */
6621 if (!NILP (Vmouse_autoselect_window
) && !popup_activated ())
6623 static Lisp_Object last_mouse_window
;
6624 Lisp_Object window
= window_from_coordinates
6625 (f
, event
->xmotion
.x
, event
->xmotion
.y
, 0, 0);
6627 /* Window will be selected only when it is not selected now and
6628 last mouse movement event was not in it. Minibuffer window
6629 will be selected only when it is active. */
6630 if (WINDOWP (window
)
6631 && !EQ (window
, last_mouse_window
)
6632 && !EQ (window
, selected_window
)
6633 /* For click-to-focus window managers
6634 create event iff we don't leave the
6636 && (focus_follows_mouse
6637 || (EQ (XWINDOW (window
)->frame
,
6638 XWINDOW (selected_window
)->frame
))))
6640 inev
.ie
.kind
= SELECT_WINDOW_EVENT
;
6641 inev
.ie
.frame_or_window
= window
;
6643 /* Remember the last window where we saw the mouse. */
6644 last_mouse_window
= window
;
6646 if (!note_mouse_movement (f
, &event
->xmotion
))
6647 help_echo_string
= previous_help_echo_string
;
6651 #ifndef USE_TOOLKIT_SCROLL_BARS
6652 struct scroll_bar
*bar
6653 = x_window_to_scroll_bar (event
->xmotion
.display
,
6654 event
->xmotion
.window
);
6657 x_scroll_bar_note_movement (bar
, &event
->xmotion
);
6658 #endif /* USE_TOOLKIT_SCROLL_BARS */
6660 /* If we move outside the frame, then we're
6661 certainly no longer on any text in the frame. */
6662 clear_mouse_face (hlinfo
);
6665 /* If the contents of the global variable help_echo_string
6666 has changed, generate a HELP_EVENT. */
6667 if (!NILP (help_echo_string
)
6668 || !NILP (previous_help_echo_string
))
6673 case ConfigureNotify
:
6674 f
= x_top_window_to_frame (dpyinfo
, event
->xconfigure
.window
);
6678 && event
->xconfigure
.window
== FRAME_X_WINDOW (f
))
6680 xg_frame_resized (f
, event
->xconfigure
.width
,
6681 event
->xconfigure
.height
);
6687 #ifndef USE_X_TOOLKIT
6689 int width
= FRAME_PIXEL_TO_TEXT_WIDTH (f
, event
->xconfigure
.width
);
6690 int height
= FRAME_PIXEL_TO_TEXT_HEIGHT (f
, event
->xconfigure
.height
);
6692 /* In the toolkit version, change_frame_size
6693 is called by the code that handles resizing
6694 of the EmacsFrame widget. */
6696 /* Even if the number of character rows and columns has
6697 not changed, the font size may have changed, so we need
6698 to check the pixel dimensions as well. */
6699 if (width
!= FRAME_TEXT_WIDTH (f
)
6700 || height
!= FRAME_TEXT_HEIGHT (f
)
6701 || event
->xconfigure
.width
!= FRAME_PIXEL_WIDTH (f
)
6702 || event
->xconfigure
.height
!= FRAME_PIXEL_HEIGHT (f
))
6704 change_frame_size (f
, width
, height
, 0, 1, 0, 1);
6705 x_clear_under_internal_border (f
);
6706 SET_FRAME_GARBAGED (f
);
6707 cancel_mouse_face (f
);
6710 /** FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; **/
6711 /** FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; **/
6712 #endif /* not USE_GTK */
6716 /* GTK creates windows but doesn't map them.
6717 Only get real positions when mapped. */
6718 if (FRAME_GTK_OUTER_WIDGET (f
)
6719 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f
)))
6721 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6724 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
6725 xic_set_statusarea (f
);
6734 /* If we decide we want to generate an event to be seen
6735 by the rest of Emacs, we put it here. */
6736 bool tool_bar_p
= 0;
6738 memset (&compose_status
, 0, sizeof (compose_status
));
6739 dpyinfo
->last_mouse_glyph_frame
= NULL
;
6740 dpyinfo
->last_user_time
= event
->xbutton
.time
;
6742 f
= (x_mouse_grabbed (dpyinfo
) ? dpyinfo
->last_mouse_frame
6743 : x_window_to_frame (dpyinfo
, event
->xbutton
.window
));
6746 if (f
&& xg_event_is_for_scrollbar (f
, event
))
6751 #if ! defined (USE_GTK)
6752 /* Is this in the tool-bar? */
6753 if (WINDOWP (f
->tool_bar_window
)
6754 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
6757 int x
= event
->xbutton
.x
;
6758 int y
= event
->xbutton
.y
;
6760 window
= window_from_coordinates (f
, x
, y
, 0, 1);
6761 tool_bar_p
= EQ (window
, f
->tool_bar_window
);
6763 if (tool_bar_p
&& event
->xbutton
.button
< 4)
6764 handle_tool_bar_click
6765 (f
, x
, y
, event
->xbutton
.type
== ButtonPress
,
6766 x_x_to_emacs_modifiers (dpyinfo
, event
->xbutton
.state
));
6768 #endif /* !USE_GTK */
6771 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6772 if (! popup_activated ())
6775 if (ignore_next_mouse_click_timeout
)
6777 if (event
->type
== ButtonPress
6778 && event
->xbutton
.time
> ignore_next_mouse_click_timeout
)
6780 ignore_next_mouse_click_timeout
= 0;
6781 construct_mouse_click (&inev
.ie
, &event
->xbutton
, f
);
6783 if (event
->type
== ButtonRelease
)
6784 ignore_next_mouse_click_timeout
= 0;
6787 construct_mouse_click (&inev
.ie
, &event
->xbutton
, f
);
6789 if (FRAME_X_EMBEDDED_P (f
))
6790 xembed_send_message (f
, event
->xbutton
.time
,
6791 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
6795 struct scroll_bar
*bar
6796 = x_window_to_scroll_bar (event
->xbutton
.display
,
6797 event
->xbutton
.window
);
6799 #ifdef USE_TOOLKIT_SCROLL_BARS
6800 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6802 if (bar
&& event
->xbutton
.state
& ControlMask
)
6804 x_scroll_bar_handle_click (bar
, event
, &inev
.ie
);
6805 *finish
= X_EVENT_DROP
;
6807 #else /* not USE_TOOLKIT_SCROLL_BARS */
6809 x_scroll_bar_handle_click (bar
, event
, &inev
.ie
);
6810 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6813 if (event
->type
== ButtonPress
)
6815 dpyinfo
->grabbed
|= (1 << event
->xbutton
.button
);
6816 dpyinfo
->last_mouse_frame
= f
;
6817 #if ! defined (USE_GTK)
6818 if (f
&& !tool_bar_p
)
6819 f
->last_tool_bar_item
= -1;
6820 #endif /* not USE_GTK */
6823 dpyinfo
->grabbed
&= ~(1 << event
->xbutton
.button
);
6825 /* Ignore any mouse motion that happened before this event;
6826 any subsequent mouse-movement Emacs events should reflect
6827 only motion after the ButtonPress/Release. */
6831 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6832 f
= x_menubar_window_to_frame (dpyinfo
, event
);
6833 /* For a down-event in the menu bar,
6834 don't pass it to Xt right now.
6835 Instead, save it away
6836 and we will pass it to Xt from kbd_buffer_get_event.
6837 That way, we can run some Lisp code first. */
6838 if (! popup_activated ()
6840 /* Gtk+ menus only react to the first three buttons. */
6841 && event
->xbutton
.button
< 3
6843 && f
&& event
->type
== ButtonPress
6844 /* Verify the event is really within the menu bar
6845 and not just sent to it due to grabbing. */
6846 && event
->xbutton
.x
>= 0
6847 && event
->xbutton
.x
< FRAME_PIXEL_WIDTH (f
)
6848 && event
->xbutton
.y
>= 0
6849 && event
->xbutton
.y
< f
->output_data
.x
->menubar_height
6850 && event
->xbutton
.same_screen
)
6852 if (!f
->output_data
.x
->saved_menu_event
)
6853 f
->output_data
.x
->saved_menu_event
= xmalloc (sizeof *event
);
6854 *f
->output_data
.x
->saved_menu_event
= *event
;
6855 inev
.ie
.kind
= MENU_BAR_ACTIVATE_EVENT
;
6856 XSETFRAME (inev
.ie
.frame_or_window
, f
);
6857 *finish
= X_EVENT_DROP
;
6861 #endif /* USE_X_TOOLKIT || USE_GTK */
6865 case CirculateNotify
:
6868 case CirculateRequest
:
6871 case VisibilityNotify
:
6875 /* Someone has changed the keyboard mapping - update the
6877 switch (event
->xmapping
.request
)
6879 case MappingModifier
:
6880 x_find_modifier_meanings (dpyinfo
);
6881 /* This is meant to fall through. */
6882 case MappingKeyboard
:
6883 XRefreshKeyboardMapping ((XMappingEvent
*) &event
->xmapping
);
6888 xft_settings_event (dpyinfo
, event
);
6893 #ifdef USE_X_TOOLKIT
6895 if (*finish
!= X_EVENT_DROP
)
6896 XtDispatchEvent ((XEvent
*) event
);
6898 #endif /* USE_X_TOOLKIT */
6903 if (inev
.ie
.kind
!= NO_EVENT
)
6905 kbd_buffer_store_event_hold (&inev
.ie
, hold_quit
);
6910 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
6915 XSETFRAME (frame
, f
);
6921 any_help_event_p
= 1;
6922 gen_help_event (help_echo_string
, frame
, help_echo_window
,
6923 help_echo_object
, help_echo_pos
);
6927 help_echo_string
= Qnil
;
6928 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
6937 /* Handles the XEvent EVENT on display DISPLAY.
6938 This is used for event loops outside the normal event handling,
6939 i.e. looping while a popup menu or a dialog is posted.
6941 Returns the value handle_one_xevent sets in the finish argument. */
6943 x_dispatch_event (XEvent
*event
, Display
*display
)
6945 struct x_display_info
*dpyinfo
;
6946 int finish
= X_EVENT_NORMAL
;
6948 dpyinfo
= x_display_info_for_display (display
);
6951 handle_one_xevent (dpyinfo
, event
, &finish
, 0);
6956 /* Read events coming from the X server.
6957 Return as soon as there are no more events to be read.
6959 Return the number of characters stored into the buffer,
6960 thus pretending to be `read' (except the characters we store
6961 in the keyboard buffer can be multibyte, so are not necessarily
6965 XTread_socket (struct terminal
*terminal
, struct input_event
*hold_quit
)
6968 int event_found
= 0;
6969 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
6973 /* For debugging, this gives a way to fake an I/O error. */
6974 if (dpyinfo
== XTread_socket_fake_io_error
)
6976 XTread_socket_fake_io_error
= 0;
6977 x_io_error_quitter (dpyinfo
->display
);
6981 while (XPending (dpyinfo
->display
))
6986 XNextEvent (dpyinfo
->display
, &event
);
6989 /* Filter events for the current X input method. */
6990 if (x_filter_event (dpyinfo
, &event
))
6995 count
+= handle_one_xevent (dpyinfo
, &event
, &finish
, hold_quit
);
6997 if (finish
== X_EVENT_GOTO_OUT
)
7003 /* For GTK we must use the GTK event loop. But XEvents gets passed
7004 to our filter function above, and then to the big event switch.
7005 We use a bunch of globals to communicate with our filter function,
7006 that is kind of ugly, but it works.
7008 There is no way to do one display at the time, GTK just does events
7009 from all displays. */
7011 while (gtk_events_pending ())
7013 current_count
= count
;
7014 current_hold_quit
= hold_quit
;
7016 gtk_main_iteration ();
7018 count
= current_count
;
7020 current_hold_quit
= 0;
7022 if (current_finish
== X_EVENT_GOTO_OUT
)
7025 #endif /* USE_GTK */
7027 /* On some systems, an X bug causes Emacs to get no more events
7028 when the window is destroyed. Detect that. (1994.) */
7031 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7032 One XNOOP in 100 loops will make Emacs terminate.
7033 B. Bretthauer, 1994 */
7035 if (x_noop_count
>= 100)
7039 if (next_noop_dpyinfo
== 0)
7040 next_noop_dpyinfo
= x_display_list
;
7042 XNoOp (next_noop_dpyinfo
->display
);
7044 /* Each time we get here, cycle through the displays now open. */
7045 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
7049 /* If the focus was just given to an auto-raising frame,
7050 raise it now. FIXME: handle more than one such frame. */
7051 if (dpyinfo
->x_pending_autoraise_frame
)
7053 x_raise_frame (dpyinfo
->x_pending_autoraise_frame
);
7054 dpyinfo
->x_pending_autoraise_frame
= NULL
;
7065 /***********************************************************************
7067 ***********************************************************************/
7069 /* Set clipping for output in glyph row ROW. W is the window in which
7070 we operate. GC is the graphics context to set clipping in.
7072 ROW may be a text row or, e.g., a mode line. Text rows must be
7073 clipped to the interior of the window dedicated to text display,
7074 mode lines must be clipped to the whole window. */
7077 x_clip_to_row (struct window
*w
, struct glyph_row
*row
,
7078 enum glyph_row_area area
, GC gc
)
7080 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7081 XRectangle clip_rect
;
7082 int window_x
, window_y
, window_width
;
7084 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
7086 clip_rect
.x
= window_x
;
7087 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, row
->y
));
7088 clip_rect
.y
= max (clip_rect
.y
, window_y
);
7089 clip_rect
.width
= window_width
;
7090 clip_rect
.height
= row
->visible_height
;
7092 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
7096 /* Draw a hollow box cursor on window W in glyph row ROW. */
7099 x_draw_hollow_cursor (struct window
*w
, struct glyph_row
*row
)
7101 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7102 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
7103 Display
*dpy
= FRAME_X_DISPLAY (f
);
7106 struct glyph
*cursor_glyph
;
7109 /* Get the glyph the cursor is on. If we can't tell because
7110 the current matrix is invalid or such, give up. */
7111 cursor_glyph
= get_phys_cursor_glyph (w
);
7112 if (cursor_glyph
== NULL
)
7115 /* Compute frame-relative coordinates for phys cursor. */
7116 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &x
, &y
, &h
);
7117 wd
= w
->phys_cursor_width
;
7119 /* The foreground of cursor_gc is typically the same as the normal
7120 background color, which can cause the cursor box to be invisible. */
7121 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7122 if (dpyinfo
->scratch_cursor_gc
)
7123 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
7125 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
7126 GCForeground
, &xgcv
);
7127 gc
= dpyinfo
->scratch_cursor_gc
;
7129 /* Set clipping, draw the rectangle, and reset clipping again. */
7130 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7131 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
- 1);
7132 XSetClipMask (dpy
, gc
, None
);
7136 /* Draw a bar cursor on window W in glyph row ROW.
7138 Implementation note: One would like to draw a bar cursor with an
7139 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7140 Unfortunately, I didn't find a font yet that has this property set.
7144 x_draw_bar_cursor (struct window
*w
, struct glyph_row
*row
, int width
, enum text_cursor_kinds kind
)
7146 struct frame
*f
= XFRAME (w
->frame
);
7147 struct glyph
*cursor_glyph
;
7149 /* If cursor is out of bounds, don't draw garbage. This can happen
7150 in mini-buffer windows when switching between echo area glyphs
7152 cursor_glyph
= get_phys_cursor_glyph (w
);
7153 if (cursor_glyph
== NULL
)
7156 /* If on an image, draw like a normal cursor. That's usually better
7157 visible than drawing a bar, esp. if the image is large so that
7158 the bar might not be in the window. */
7159 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7161 struct glyph_row
*r
;
7162 r
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7163 draw_phys_cursor_glyph (w
, r
, DRAW_CURSOR
);
7167 Display
*dpy
= FRAME_X_DISPLAY (f
);
7168 Window window
= FRAME_X_WINDOW (f
);
7169 GC gc
= FRAME_DISPLAY_INFO (f
)->scratch_cursor_gc
;
7170 unsigned long mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
7171 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7174 /* If the glyph's background equals the color we normally draw
7175 the bars cursor in, the bar cursor in its normal color is
7176 invisible. Use the glyph's foreground color instead in this
7177 case, on the assumption that the glyph's colors are chosen so
7178 that the glyph is legible. */
7179 if (face
->background
== f
->output_data
.x
->cursor_pixel
)
7180 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
7182 xgcv
.background
= xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
7183 xgcv
.graphics_exposures
= 0;
7186 XChangeGC (dpy
, gc
, mask
, &xgcv
);
7189 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
7190 FRAME_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
7193 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
7195 if (kind
== BAR_CURSOR
)
7197 int x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7200 width
= FRAME_CURSOR_WIDTH (f
);
7201 width
= min (cursor_glyph
->pixel_width
, width
);
7203 w
->phys_cursor_width
= width
;
7205 /* If the character under cursor is R2L, draw the bar cursor
7206 on the right of its glyph, rather than on the left. */
7207 if ((cursor_glyph
->resolved_level
& 1) != 0)
7208 x
+= cursor_glyph
->pixel_width
- width
;
7210 XFillRectangle (dpy
, window
, gc
, x
,
7211 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7212 width
, row
->height
);
7216 int dummy_x
, dummy_y
, dummy_h
;
7219 width
= row
->height
;
7221 width
= min (row
->height
, width
);
7223 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &dummy_x
,
7224 &dummy_y
, &dummy_h
);
7226 XFillRectangle (dpy
, window
, gc
,
7227 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
7228 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7229 row
->height
- width
),
7230 w
->phys_cursor_width
, width
);
7233 XSetClipMask (dpy
, gc
, None
);
7238 /* RIF: Define cursor CURSOR on frame F. */
7241 x_define_frame_cursor (struct frame
*f
, Cursor cursor
)
7243 if (!f
->pointer_invisible
7244 && f
->output_data
.x
->current_cursor
!= cursor
)
7245 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
7246 f
->output_data
.x
->current_cursor
= cursor
;
7250 /* RIF: Clear area on frame F. */
7253 x_clear_frame_area (struct frame
*f
, int x
, int y
, int width
, int height
)
7255 x_clear_area (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), x
, y
, width
, height
);
7257 /* Must queue a redraw, because scroll bars might have been cleared. */
7258 if (FRAME_GTK_WIDGET (f
))
7259 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f
));
7264 /* RIF: Draw cursor on window W. */
7267 x_draw_window_cursor (struct window
*w
, struct glyph_row
*glyph_row
, int x
,
7268 int y
, enum text_cursor_kinds cursor_type
,
7269 int cursor_width
, bool on_p
, bool active_p
)
7271 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7275 w
->phys_cursor_type
= cursor_type
;
7276 w
->phys_cursor_on_p
= 1;
7278 if (glyph_row
->exact_window_width_line_p
7279 && (glyph_row
->reversed_p
7280 ? (w
->phys_cursor
.hpos
< 0)
7281 : (w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])))
7283 glyph_row
->cursor_in_fringe_p
= 1;
7284 draw_fringe_bitmap (w
, glyph_row
, glyph_row
->reversed_p
);
7288 switch (cursor_type
)
7290 case HOLLOW_BOX_CURSOR
:
7291 x_draw_hollow_cursor (w
, glyph_row
);
7294 case FILLED_BOX_CURSOR
:
7295 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7299 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
7303 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
7307 w
->phys_cursor_width
= 0;
7316 if (w
== XWINDOW (f
->selected_window
))
7317 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
7318 xic_set_preeditarea (w
, x
, y
);
7322 XFlush (FRAME_X_DISPLAY (f
));
7328 /* Make the x-window of frame F use the gnu icon bitmap. */
7331 x_bitmap_icon (struct frame
*f
, Lisp_Object file
)
7333 ptrdiff_t bitmap_id
;
7335 if (FRAME_X_WINDOW (f
) == 0)
7338 /* Free up our existing icon bitmap and mask if any. */
7339 if (f
->output_data
.x
->icon_bitmap
> 0)
7340 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7341 f
->output_data
.x
->icon_bitmap
= 0;
7346 /* Use gtk_window_set_icon_from_file () if available,
7347 It's not restricted to bitmaps */
7348 if (xg_set_icon (f
, file
))
7350 #endif /* USE_GTK */
7351 bitmap_id
= x_create_bitmap_from_file (f
, file
);
7352 x_create_bitmap_mask (f
, bitmap_id
);
7356 /* Create the GNU bitmap and mask if necessary. */
7357 if (FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
7363 if (FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
== -2
7364 || xg_set_icon (f
, xg_default_icon_file
)
7365 || xg_set_icon_from_xpm_data (f
, gnu_xpm_bits
))
7367 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= -2;
7371 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7373 rc
= x_create_bitmap_from_xpm_data (f
, gnu_xpm_bits
);
7375 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7379 /* If all else fails, use the (black and white) xbm image. */
7382 rc
= x_create_bitmap_from_data (f
, (char *) gnu_xbm_bits
,
7383 gnu_xbm_width
, gnu_xbm_height
);
7387 FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
= rc
;
7388 x_create_bitmap_mask (f
, FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
);
7392 /* The first time we create the GNU bitmap and mask,
7393 this increments the ref-count one extra time.
7394 As a result, the GNU bitmap and mask are never freed.
7395 That way, we don't have to worry about allocating it again. */
7396 x_reference_bitmap (f
, FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
);
7398 bitmap_id
= FRAME_DISPLAY_INFO (f
)->icon_bitmap_id
;
7401 x_wm_set_icon_pixmap (f
, bitmap_id
);
7402 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
7408 /* Make the x-window of frame F use a rectangle with text.
7409 Use ICON_NAME as the text. */
7412 x_text_icon (struct frame
*f
, const char *icon_name
)
7414 if (FRAME_X_WINDOW (f
) == 0)
7419 text
.value
= (unsigned char *) icon_name
;
7420 text
.encoding
= XA_STRING
;
7422 text
.nitems
= strlen (icon_name
);
7423 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
), &text
);
7426 if (f
->output_data
.x
->icon_bitmap
> 0)
7427 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
7428 f
->output_data
.x
->icon_bitmap
= 0;
7429 x_wm_set_icon_pixmap (f
, 0);
7434 #define X_ERROR_MESSAGE_SIZE 200
7436 /* If non-nil, this should be a string.
7437 It means catch X errors and store the error message in this string.
7439 The reason we use a stack is that x_catch_error/x_uncatch_error can
7440 be called from a signal handler.
7443 struct x_error_message_stack
{
7444 char string
[X_ERROR_MESSAGE_SIZE
];
7446 struct x_error_message_stack
*prev
;
7448 static struct x_error_message_stack
*x_error_message
;
7450 /* An X error handler which stores the error message in
7451 *x_error_message. This is called from x_error_handler if
7452 x_catch_errors is in effect. */
7455 x_error_catcher (Display
*display
, XErrorEvent
*event
)
7457 XGetErrorText (display
, event
->error_code
,
7458 x_error_message
->string
,
7459 X_ERROR_MESSAGE_SIZE
);
7462 /* Begin trapping X errors for display DPY. Actually we trap X errors
7463 for all displays, but DPY should be the display you are actually
7466 After calling this function, X protocol errors no longer cause
7467 Emacs to exit; instead, they are recorded in the string
7468 stored in *x_error_message.
7470 Calling x_check_errors signals an Emacs error if an X error has
7471 occurred since the last call to x_catch_errors or x_check_errors.
7473 Calling x_uncatch_errors resumes the normal error handling. */
7476 x_catch_errors (Display
*dpy
)
7478 struct x_error_message_stack
*data
= xmalloc (sizeof *data
);
7480 /* Make sure any errors from previous requests have been dealt with. */
7484 data
->string
[0] = 0;
7485 data
->prev
= x_error_message
;
7486 x_error_message
= data
;
7489 /* Undo the last x_catch_errors call.
7490 DPY should be the display that was passed to x_catch_errors. */
7493 x_uncatch_errors (void)
7495 struct x_error_message_stack
*tmp
;
7499 /* The display may have been closed before this function is called.
7500 Check if it is still open before calling XSync. */
7501 if (x_display_info_for_display (x_error_message
->dpy
) != 0)
7502 XSync (x_error_message
->dpy
, False
);
7504 tmp
= x_error_message
;
7505 x_error_message
= x_error_message
->prev
;
7510 /* If any X protocol errors have arrived since the last call to
7511 x_catch_errors or x_check_errors, signal an Emacs error using
7512 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7515 x_check_errors (Display
*dpy
, const char *format
)
7517 /* Make sure to catch any errors incurred so far. */
7520 if (x_error_message
->string
[0])
7522 char string
[X_ERROR_MESSAGE_SIZE
];
7523 memcpy (string
, x_error_message
->string
, X_ERROR_MESSAGE_SIZE
);
7524 x_uncatch_errors ();
7525 error (format
, string
);
7529 /* Nonzero if we had any X protocol errors
7530 since we did x_catch_errors on DPY. */
7533 x_had_errors_p (Display
*dpy
)
7535 /* Make sure to catch any errors incurred so far. */
7538 return x_error_message
->string
[0] != 0;
7541 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7544 x_clear_errors (Display
*dpy
)
7546 x_error_message
->string
[0] = 0;
7549 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7550 * idea. --lorentey */
7551 /* Close off all unclosed x_catch_errors calls. */
7554 x_fully_uncatch_errors (void)
7556 while (x_error_message
)
7557 x_uncatch_errors ();
7562 static unsigned int x_wire_count
;
7565 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
7570 /************************************************************************
7572 ************************************************************************/
7574 /* Error message passed to x_connection_closed. */
7576 static char *error_msg
;
7578 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7579 the text of an error message that lead to the connection loss. */
7582 x_connection_closed (Display
*dpy
, const char *error_message
)
7584 struct x_display_info
*dpyinfo
= x_display_info_for_display (dpy
);
7585 Lisp_Object frame
, tail
;
7586 ptrdiff_t idx
= SPECPDL_INDEX ();
7588 error_msg
= alloca (strlen (error_message
) + 1);
7589 strcpy (error_msg
, error_message
);
7591 /* Inhibit redisplay while frames are being deleted. */
7592 specbind (Qinhibit_redisplay
, Qt
);
7596 /* Protect display from being closed when we delete the last
7598 dpyinfo
->reference_count
++;
7599 dpyinfo
->terminal
->reference_count
++;
7602 /* First delete frames whose mini-buffers are on frames
7603 that are on the dead display. */
7604 FOR_EACH_FRAME (tail
, frame
)
7606 Lisp_Object minibuf_frame
;
7608 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
7609 if (FRAME_X_P (XFRAME (frame
))
7610 && FRAME_X_P (XFRAME (minibuf_frame
))
7611 && ! EQ (frame
, minibuf_frame
)
7612 && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
7613 delete_frame (frame
, Qnoelisp
);
7616 /* Now delete all remaining frames on the dead display.
7617 We are now sure none of these is used as the mini-buffer
7618 for another frame that we need to delete. */
7619 FOR_EACH_FRAME (tail
, frame
)
7620 if (FRAME_X_P (XFRAME (frame
))
7621 && FRAME_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
7623 /* Set this to t so that delete_frame won't get confused
7624 trying to find a replacement. */
7625 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame
)), Qt
);
7626 delete_frame (frame
, Qnoelisp
);
7629 /* If DPYINFO is null, this means we didn't open the display in the
7630 first place, so don't try to close it. */
7633 /* We can not call XtCloseDisplay here because it calls XSync.
7634 XSync inside the error handler apparently hangs Emacs. On
7635 current Xt versions, this isn't needed either. */
7637 /* A long-standing GTK bug prevents proper disconnect handling
7638 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
7639 the resulting Glib error message loop filled a user's disk.
7640 To avoid this, kill Emacs unconditionally on disconnect. */
7641 shut_down_emacs (0, Qnil
);
7642 fprintf (stderr
, "%s\n\
7643 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
7644 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
7645 For details, see etc/PROBLEMS.\n",
7648 #endif /* USE_GTK */
7650 /* Indicate that this display is dead. */
7651 dpyinfo
->display
= 0;
7653 dpyinfo
->reference_count
--;
7654 dpyinfo
->terminal
->reference_count
--;
7655 if (dpyinfo
->reference_count
!= 0)
7656 /* We have just closed all frames on this display. */
7661 XSETTERMINAL (tmp
, dpyinfo
->terminal
);
7662 Fdelete_terminal (tmp
, Qnoelisp
);
7666 if (terminal_list
== 0)
7668 fprintf (stderr
, "%s\n", error_msg
);
7669 Fkill_emacs (make_number (70));
7673 totally_unblock_input ();
7675 unbind_to (idx
, Qnil
);
7676 clear_waiting_for_input ();
7678 /* Tell GCC not to suggest attribute 'noreturn' for this function. */
7679 IF_LINT (if (! terminal_list
) return; )
7681 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7682 longjmp), because returning from this function would get us back into
7683 Xlib's code which will directly call `exit'. */
7684 error ("%s", error_msg
);
7687 /* We specifically use it before defining it, so that gcc doesn't inline it,
7688 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7689 static void x_error_quitter (Display
*, XErrorEvent
*);
7691 /* This is the first-level handler for X protocol errors.
7692 It calls x_error_quitter or x_error_catcher. */
7695 x_error_handler (Display
*display
, XErrorEvent
*event
)
7697 #if defined USE_GTK && defined HAVE_GTK3
7698 if ((event
->error_code
== BadMatch
|| event
->error_code
== BadWindow
)
7699 && event
->request_code
== X_SetInputFocus
)
7705 if (x_error_message
)
7706 x_error_catcher (display
, event
);
7708 x_error_quitter (display
, event
);
7712 /* This is the usual handler for X protocol errors.
7713 It kills all frames on the display that we got the error for.
7714 If that was the only one, it prints an error message and kills Emacs. */
7716 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7718 /* On older GCC versions, just putting x_error_quitter
7719 after x_error_handler prevents inlining into the former. */
7721 static void NO_INLINE
7722 x_error_quitter (Display
*display
, XErrorEvent
*event
)
7724 char buf
[256], buf1
[356];
7726 /* Ignore BadName errors. They can happen because of fonts
7727 or colors that are not defined. */
7729 if (event
->error_code
== BadName
)
7732 /* Note that there is no real way portable across R3/R4 to get the
7733 original error handler. */
7735 XGetErrorText (display
, event
->error_code
, buf
, sizeof (buf
));
7736 sprintf (buf1
, "X protocol error: %s on protocol request %d",
7737 buf
, event
->request_code
);
7738 x_connection_closed (display
, buf1
);
7742 /* This is the handler for X IO errors, always.
7743 It kills all frames on the display that we lost touch with.
7744 If that was the only one, it prints an error message and kills Emacs. */
7747 x_io_error_quitter (Display
*display
)
7751 snprintf (buf
, sizeof buf
, "Connection lost to X server `%s'",
7752 DisplayString (display
));
7753 x_connection_closed (display
, buf
);
7757 /* Changing the font of the frame. */
7759 /* Give frame F the font FONT-OBJECT as its default font. The return
7760 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
7761 frame. If it is negative, generate a new fontset from
7765 x_new_font (struct frame
*f
, Lisp_Object font_object
, int fontset
)
7767 struct font
*font
= XFONT_OBJECT (font_object
);
7771 fontset
= fontset_from_font (font_object
);
7772 FRAME_FONTSET (f
) = fontset
;
7773 if (FRAME_FONT (f
) == font
)
7774 /* This font is already set in frame F. There's nothing more to
7778 FRAME_FONT (f
) = font
;
7779 FRAME_BASELINE_OFFSET (f
) = font
->baseline_offset
;
7780 FRAME_COLUMN_WIDTH (f
) = font
->average_width
;
7781 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (font
);
7783 FRAME_TOOL_BAR_HEIGHT (f
) = FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
);
7784 FRAME_MENU_BAR_HEIGHT (f
) = FRAME_MENU_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
);
7786 compute_fringe_widths (f
, 1);
7788 /* Compute character columns occupied by scrollbar.
7790 Don't do things differently for non-toolkit scrollbars
7792 unit
= FRAME_COLUMN_WIDTH (f
);
7793 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
7794 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
7795 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + unit
- 1) / unit
;
7797 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + unit
- 1) / unit
;
7799 if (FRAME_X_WINDOW (f
) != 0)
7801 /* Don't change the size of a tip frame; there's no point in
7802 doing it because it's done in Fx_show_tip, and it leads to
7803 problems because the tip frame has no widget. */
7804 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7805 x_set_window_size (f
, 0, FRAME_COLS (f
) * FRAME_COLUMN_WIDTH (f
),
7806 FRAME_LINES (f
) * FRAME_LINE_HEIGHT (f
), 1);
7811 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
7814 xic_set_xfontset (f
, SSDATA (fontset_ascii (fontset
)));
7823 /***********************************************************************
7825 ***********************************************************************/
7831 /* XIM destroy callback function, which is called whenever the
7832 connection to input method XIM dies. CLIENT_DATA contains a
7833 pointer to the x_display_info structure corresponding to XIM. */
7836 xim_destroy_callback (XIM xim
, XPointer client_data
, XPointer call_data
)
7838 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
7839 Lisp_Object frame
, tail
;
7843 /* No need to call XDestroyIC.. */
7844 FOR_EACH_FRAME (tail
, frame
)
7846 struct frame
*f
= XFRAME (frame
);
7847 if (FRAME_X_P (f
) && FRAME_DISPLAY_INFO (f
) == dpyinfo
)
7849 FRAME_XIC (f
) = NULL
;
7850 xic_free_xfontset (f
);
7854 /* No need to call XCloseIM. */
7855 dpyinfo
->xim
= NULL
;
7856 XFree (dpyinfo
->xim_styles
);
7860 #endif /* HAVE_X11R6 */
7863 /* This isn't prototyped in OSF 5.0 or 5.1a. */
7864 extern char *XSetIMValues (XIM
, ...);
7867 /* Open the connection to the XIM server on display DPYINFO.
7868 RESOURCE_NAME is the resource name Emacs uses. */
7871 xim_open_dpy (struct x_display_info
*dpyinfo
, char *resource_name
)
7879 XCloseIM (dpyinfo
->xim
);
7880 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
,
7887 XIMCallback destroy
;
7890 /* Get supported styles and XIM values. */
7891 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
7894 destroy
.callback
= xim_destroy_callback
;
7895 destroy
.client_data
= (XPointer
)dpyinfo
;
7896 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
7902 #endif /* HAVE_XIM */
7903 dpyinfo
->xim
= NULL
;
7907 #ifdef HAVE_X11R6_XIM
7909 /* XIM instantiate callback function, which is called whenever an XIM
7910 server is available. DISPLAY is the display of the XIM.
7911 CLIENT_DATA contains a pointer to an xim_inst_t structure created
7912 when the callback was registered. */
7915 xim_instantiate_callback (Display
*display
, XPointer client_data
, XPointer call_data
)
7917 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
7918 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
7920 /* We don't support multiple XIM connections. */
7924 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
7926 /* Create XIC for the existing frames on the same display, as long
7927 as they have no XIC. */
7928 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
7930 Lisp_Object tail
, frame
;
7933 FOR_EACH_FRAME (tail
, frame
)
7935 struct frame
*f
= XFRAME (frame
);
7938 && FRAME_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
7939 if (FRAME_XIC (f
) == NULL
)
7941 create_frame_xic (f
);
7942 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
7943 xic_set_statusarea (f
);
7944 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
7946 struct window
*w
= XWINDOW (f
->selected_window
);
7947 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
7956 #endif /* HAVE_X11R6_XIM */
7959 /* Open a connection to the XIM server on display DPYINFO.
7960 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
7961 connection only at the first time. On X11R6, open the connection
7962 in the XIM instantiate callback function. */
7965 xim_initialize (struct x_display_info
*dpyinfo
, char *resource_name
)
7967 dpyinfo
->xim
= NULL
;
7971 #ifdef HAVE_X11R6_XIM
7972 struct xim_inst_t
*xim_inst
= xmalloc (sizeof *xim_inst
);
7975 dpyinfo
->xim_callback_data
= xim_inst
;
7976 xim_inst
->dpyinfo
= dpyinfo
;
7977 xim_inst
->resource_name
= xstrdup (resource_name
);
7978 ret
= XRegisterIMInstantiateCallback
7979 (dpyinfo
->display
, dpyinfo
->xrdb
, xim_inst
->resource_name
,
7980 emacs_class
, xim_instantiate_callback
,
7981 /* This is XPointer in XFree86 but (XPointer *)
7982 on Tru64, at least, hence the configure test. */
7983 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
7984 eassert (ret
== True
);
7985 #else /* not HAVE_X11R6_XIM */
7986 xim_open_dpy (dpyinfo
, resource_name
);
7987 #endif /* not HAVE_X11R6_XIM */
7989 #endif /* HAVE_XIM */
7993 /* Close the connection to the XIM server on display DPYINFO. */
7996 xim_close_dpy (struct x_display_info
*dpyinfo
)
8001 #ifdef HAVE_X11R6_XIM
8002 struct xim_inst_t
*xim_inst
= dpyinfo
->xim_callback_data
;
8004 if (dpyinfo
->display
)
8006 Bool ret
= XUnregisterIMInstantiateCallback
8007 (dpyinfo
->display
, dpyinfo
->xrdb
, xim_inst
->resource_name
,
8008 emacs_class
, xim_instantiate_callback
,
8009 (XRegisterIMInstantiateCallback_arg6
) xim_inst
);
8010 eassert (ret
== True
);
8012 xfree (xim_inst
->resource_name
);
8014 #endif /* HAVE_X11R6_XIM */
8015 if (dpyinfo
->display
)
8016 XCloseIM (dpyinfo
->xim
);
8017 dpyinfo
->xim
= NULL
;
8018 XFree (dpyinfo
->xim_styles
);
8020 #endif /* HAVE_XIM */
8023 #endif /* not HAVE_X11R6_XIM */
8027 /* Calculate the absolute position in frame F
8028 from its current recorded position values and gravity. */
8031 x_calc_absolute_position (struct frame
*f
)
8033 int flags
= f
->size_hint_flags
;
8035 /* We have nothing to do if the current position
8036 is already for the top-left corner. */
8037 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
8040 /* Treat negative positions as relative to the leftmost bottommost
8041 position that fits on the screen. */
8042 if (flags
& XNegative
)
8043 f
->left_pos
= x_display_pixel_width (FRAME_DISPLAY_INFO (f
))
8044 - FRAME_PIXEL_WIDTH (f
) + f
->left_pos
;
8047 int height
= FRAME_PIXEL_HEIGHT (f
);
8049 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8050 /* Something is fishy here. When using Motif, starting Emacs with
8051 `-g -0-0', the frame appears too low by a few pixels.
8053 This seems to be so because initially, while Emacs is starting,
8054 the column widget's height and the frame's pixel height are
8055 different. The column widget's height is the right one. In
8056 later invocations, when Emacs is up, the frame's pixel height
8059 It's not obvious where the initial small difference comes from.
8060 2000-12-01, gerd. */
8062 XtVaGetValues (f
->output_data
.x
->column_widget
, XtNheight
, &height
, NULL
);
8065 if (flags
& YNegative
)
8066 f
->top_pos
= x_display_pixel_height (FRAME_DISPLAY_INFO (f
))
8067 - height
+ f
->top_pos
;
8070 /* The left_pos and top_pos
8071 are now relative to the top and left screen edges,
8072 so the flags should correspond. */
8073 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8076 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8077 to really change the position, and 0 when calling from
8078 x_make_frame_visible (in that case, XOFF and YOFF are the current
8079 position values). It is -1 when calling from x_set_frame_parameters,
8080 which means, do adjust for borders but don't change the gravity. */
8083 x_set_offset (struct frame
*f
, register int xoff
, register int yoff
, int change_gravity
)
8085 int modified_top
, modified_left
;
8087 if (change_gravity
> 0)
8091 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
8093 f
->size_hint_flags
|= XNegative
;
8095 f
->size_hint_flags
|= YNegative
;
8096 f
->win_gravity
= NorthWestGravity
;
8098 x_calc_absolute_position (f
);
8101 x_wm_set_size_hint (f
, (long) 0, 0);
8103 modified_left
= f
->left_pos
;
8104 modified_top
= f
->top_pos
;
8106 if (change_gravity
!= 0 && FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
)
8108 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8109 than the WM decorations. So we use the calculated offset instead
8110 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8111 modified_left
+= FRAME_X_OUTPUT (f
)->move_offset_left
;
8112 modified_top
+= FRAME_X_OUTPUT (f
)->move_offset_top
;
8115 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8116 modified_left
, modified_top
);
8118 x_sync_with_move (f
, f
->left_pos
, f
->top_pos
,
8119 FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8122 /* change_gravity is non-zero when this function is called from Lisp to
8123 programmatically move a frame. In that case, we call
8124 x_check_expected_move to discover if we have a "Type A" or "Type B"
8125 window manager, and, for a "Type A" window manager, adjust the position
8128 We call x_check_expected_move if a programmatic move occurred, and
8129 either the window manager type (A/B) is unknown or it is Type A but we
8130 need to compute the top/left offset adjustment for this frame. */
8132 if (change_gravity
!= 0 &&
8133 (FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_UNKNOWN
8134 || (FRAME_DISPLAY_INFO (f
)->wm_type
== X_WMTYPE_A
8135 && (FRAME_X_OUTPUT (f
)->move_offset_left
== 0
8136 && FRAME_X_OUTPUT (f
)->move_offset_top
== 0))))
8137 x_check_expected_move (f
, modified_left
, modified_top
);
8142 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8143 on the root window for frame F contains ATOMNAME.
8144 This is how a WM check shall be done according to the Window Manager
8145 Specification/Extended Window Manager Hints at
8146 http://freedesktop.org/wiki/Specifications/wm-spec. */
8149 wm_supports (struct frame
*f
, Atom want_atom
)
8152 unsigned long actual_size
, bytes_remaining
;
8153 int i
, rc
, actual_format
;
8154 Window wmcheck_window
;
8155 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8156 Window target_window
= dpyinfo
->root_window
;
8157 long max_len
= 65536;
8158 Display
*dpy
= FRAME_X_DISPLAY (f
);
8159 unsigned char *tmp_data
= NULL
;
8160 Atom target_type
= XA_WINDOW
;
8164 x_catch_errors (dpy
);
8165 rc
= XGetWindowProperty (dpy
, target_window
,
8166 dpyinfo
->Xatom_net_supporting_wm_check
,
8167 0, max_len
, False
, target_type
,
8168 &actual_type
, &actual_format
, &actual_size
,
8169 &bytes_remaining
, &tmp_data
);
8171 if (rc
!= Success
|| actual_type
!= XA_WINDOW
|| x_had_errors_p (dpy
))
8173 if (tmp_data
) XFree (tmp_data
);
8174 x_uncatch_errors ();
8179 wmcheck_window
= *(Window
*) tmp_data
;
8182 /* Check if window exists. */
8183 XSelectInput (dpy
, wmcheck_window
, StructureNotifyMask
);
8185 if (x_had_errors_p (dpy
))
8187 x_uncatch_errors ();
8192 if (dpyinfo
->net_supported_window
!= wmcheck_window
)
8194 /* Window changed, reload atoms */
8195 if (dpyinfo
->net_supported_atoms
!= NULL
)
8196 XFree (dpyinfo
->net_supported_atoms
);
8197 dpyinfo
->net_supported_atoms
= NULL
;
8198 dpyinfo
->nr_net_supported_atoms
= 0;
8199 dpyinfo
->net_supported_window
= 0;
8201 target_type
= XA_ATOM
;
8203 rc
= XGetWindowProperty (dpy
, target_window
,
8204 dpyinfo
->Xatom_net_supported
,
8205 0, max_len
, False
, target_type
,
8206 &actual_type
, &actual_format
, &actual_size
,
8207 &bytes_remaining
, &tmp_data
);
8209 if (rc
!= Success
|| actual_type
!= XA_ATOM
|| x_had_errors_p (dpy
))
8211 if (tmp_data
) XFree (tmp_data
);
8212 x_uncatch_errors ();
8217 dpyinfo
->net_supported_atoms
= (Atom
*)tmp_data
;
8218 dpyinfo
->nr_net_supported_atoms
= actual_size
;
8219 dpyinfo
->net_supported_window
= wmcheck_window
;
8224 for (i
= 0; rc
== 0 && i
< dpyinfo
->nr_net_supported_atoms
; ++i
)
8225 rc
= dpyinfo
->net_supported_atoms
[i
] == want_atom
;
8227 x_uncatch_errors ();
8234 set_wm_state (Lisp_Object frame
, int add
, Atom atom
, Atom value
)
8236 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (XFRAME (frame
));
8238 x_send_client_event (frame
, make_number (0), frame
,
8239 dpyinfo
->Xatom_net_wm_state
,
8241 /* 1 = add, 0 = remove */
8243 (make_number (add
? 1 : 0),
8245 (make_fixnum_or_float (atom
),
8247 ? list1 (make_fixnum_or_float (value
))
8252 x_set_sticky (struct frame
*f
, Lisp_Object new_value
, Lisp_Object old_value
)
8255 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8257 XSETFRAME (frame
, f
);
8259 set_wm_state (frame
, NILP (new_value
) ? 0 : 1,
8260 dpyinfo
->Xatom_net_wm_state_sticky
, None
);
8263 /* Return the current _NET_WM_STATE.
8264 SIZE_STATE is set to one of the FULLSCREEN_* values.
8265 STICKY is set to 1 if the sticky state is set, 0 if not.
8267 Return non-zero if we are not hidden, zero if we are. */
8270 get_current_wm_state (struct frame
*f
,
8276 unsigned long actual_size
, bytes_remaining
;
8277 int i
, rc
, actual_format
, is_hidden
= 0;
8278 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8279 long max_len
= 65536;
8280 Display
*dpy
= FRAME_X_DISPLAY (f
);
8281 unsigned char *tmp_data
= NULL
;
8282 Atom target_type
= XA_ATOM
;
8285 *size_state
= FULLSCREEN_NONE
;
8288 x_catch_errors (dpy
);
8289 rc
= XGetWindowProperty (dpy
, window
, dpyinfo
->Xatom_net_wm_state
,
8290 0, max_len
, False
, target_type
,
8291 &actual_type
, &actual_format
, &actual_size
,
8292 &bytes_remaining
, &tmp_data
);
8294 if (rc
!= Success
|| actual_type
!= target_type
|| x_had_errors_p (dpy
))
8296 if (tmp_data
) XFree (tmp_data
);
8297 x_uncatch_errors ();
8299 return !FRAME_ICONIFIED_P (f
);
8302 x_uncatch_errors ();
8304 for (i
= 0; i
< actual_size
; ++i
)
8306 Atom a
= ((Atom
*)tmp_data
)[i
];
8307 if (a
== dpyinfo
->Xatom_net_wm_state_hidden
)
8310 f
->output_data
.x
->net_wm_state_hidden_seen
= 1;
8312 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_horz
)
8314 if (*size_state
== FULLSCREEN_HEIGHT
)
8315 *size_state
= FULLSCREEN_MAXIMIZED
;
8317 *size_state
= FULLSCREEN_WIDTH
;
8319 else if (a
== dpyinfo
->Xatom_net_wm_state_maximized_vert
)
8321 if (*size_state
== FULLSCREEN_WIDTH
)
8322 *size_state
= FULLSCREEN_MAXIMIZED
;
8324 *size_state
= FULLSCREEN_HEIGHT
;
8326 else if (a
== dpyinfo
->Xatom_net_wm_state_fullscreen
)
8327 *size_state
= FULLSCREEN_BOTH
;
8328 else if (a
== dpyinfo
->Xatom_net_wm_state_sticky
)
8332 if (tmp_data
) XFree (tmp_data
);
8337 /* Do fullscreen as specified in extended window manager hints */
8340 do_ewmh_fullscreen (struct frame
*f
)
8342 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8343 int have_net_atom
= wm_supports (f
, dpyinfo
->Xatom_net_wm_state
);
8346 (void)get_current_wm_state (f
, FRAME_OUTER_WINDOW (f
), &cur
, &dummy
);
8348 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8349 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8351 have_net_atom
= wm_supports (f
, dpyinfo
->Xatom_net_wm_state_fullscreen
);
8353 if (have_net_atom
&& cur
!= f
->want_fullscreen
)
8357 XSETFRAME (frame
, f
);
8359 /* Keep number of calls to set_wm_state as low as possible.
8360 Some window managers, or possible Gtk+, hangs when too many
8361 are sent at once. */
8362 switch (f
->want_fullscreen
)
8364 case FULLSCREEN_BOTH
:
8365 if (cur
== FULLSCREEN_WIDTH
|| cur
== FULLSCREEN_MAXIMIZED
8366 || cur
== FULLSCREEN_HEIGHT
)
8367 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8368 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8369 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8371 case FULLSCREEN_WIDTH
:
8372 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_HEIGHT
8373 || cur
== FULLSCREEN_MAXIMIZED
)
8374 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
,
8375 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8376 if (cur
!= FULLSCREEN_MAXIMIZED
)
8377 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_horz
, None
);
8379 case FULLSCREEN_HEIGHT
:
8380 if (cur
== FULLSCREEN_BOTH
|| cur
== FULLSCREEN_WIDTH
8381 || cur
== FULLSCREEN_MAXIMIZED
)
8382 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
,
8383 dpyinfo
->Xatom_net_wm_state_maximized_horz
);
8384 if (cur
!= FULLSCREEN_MAXIMIZED
)
8385 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_vert
, None
);
8387 case FULLSCREEN_MAXIMIZED
:
8388 if (cur
== FULLSCREEN_BOTH
)
8389 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8390 set_wm_state (frame
, 1, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8391 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8393 case FULLSCREEN_NONE
:
8394 if (cur
== FULLSCREEN_BOTH
)
8395 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_fullscreen
, None
);
8397 set_wm_state (frame
, 0, dpyinfo
->Xatom_net_wm_state_maximized_horz
,
8398 dpyinfo
->Xatom_net_wm_state_maximized_vert
);
8401 f
->want_fullscreen
= FULLSCREEN_NONE
;
8405 return have_net_atom
;
8409 XTfullscreen_hook (struct frame
*f
)
8411 if (FRAME_VISIBLE_P (f
))
8414 x_check_fullscreen (f
);
8422 x_handle_net_wm_state (struct frame
*f
, const XPropertyEvent
*event
)
8424 int value
= FULLSCREEN_NONE
;
8427 int not_hidden
= get_current_wm_state (f
, event
->window
, &value
, &sticky
);
8432 case FULLSCREEN_WIDTH
:
8435 case FULLSCREEN_HEIGHT
:
8438 case FULLSCREEN_BOTH
:
8441 case FULLSCREEN_MAXIMIZED
:
8446 store_frame_param (f
, Qfullscreen
, lval
);
8447 store_frame_param (f
, Qsticky
, sticky
? Qt
: Qnil
);
8452 /* Check if we need to resize the frame due to a fullscreen request.
8453 If so needed, resize the frame. */
8455 x_check_fullscreen (struct frame
*f
)
8457 if (do_ewmh_fullscreen (f
))
8460 if (f
->output_data
.x
->parent_desc
!= FRAME_DISPLAY_INFO (f
)->root_window
)
8461 return; /* Only fullscreen without WM or with EWM hints (above). */
8463 /* Setting fullscreen to nil doesn't do anything. We could save the
8464 last non-fullscreen size and restore it, but it seems like a
8465 lot of work for this unusual case (no window manager running). */
8467 if (f
->want_fullscreen
!= FULLSCREEN_NONE
)
8469 int width
= FRAME_PIXEL_WIDTH (f
), height
= FRAME_PIXEL_HEIGHT (f
);
8470 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8472 switch (f
->want_fullscreen
)
8474 /* No difference between these two when there is no WM */
8475 case FULLSCREEN_BOTH
:
8476 case FULLSCREEN_MAXIMIZED
:
8477 width
= x_display_pixel_width (dpyinfo
);
8478 height
= x_display_pixel_height (dpyinfo
);
8480 case FULLSCREEN_WIDTH
:
8481 width
= x_display_pixel_width (dpyinfo
);
8483 case FULLSCREEN_HEIGHT
:
8484 height
= x_display_pixel_height (dpyinfo
);
8487 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8492 /* This function is called by x_set_offset to determine whether the window
8493 manager interfered with the positioning of the frame. Type A window
8494 managers position the surrounding window manager decorations a small
8495 amount above and left of the user-supplied position. Type B window
8496 managers position the surrounding window manager decorations at the
8497 user-specified position. If we detect a Type A window manager, we
8498 compensate by moving the window right and down by the proper amount. */
8501 x_check_expected_move (struct frame
*f
, int expected_left
, int expected_top
)
8503 int current_left
= 0, current_top
= 0;
8505 /* x_real_positions returns the left and top offsets of the outermost
8506 window manager window around the frame. */
8508 x_real_positions (f
, ¤t_left
, ¤t_top
);
8510 if (current_left
!= expected_left
|| current_top
!= expected_top
)
8512 /* It's a "Type A" window manager. */
8517 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_A
;
8518 FRAME_X_OUTPUT (f
)->move_offset_left
= expected_left
- current_left
;
8519 FRAME_X_OUTPUT (f
)->move_offset_top
= expected_top
- current_top
;
8521 /* Now fix the mispositioned frame's location. */
8523 adjusted_left
= expected_left
+ FRAME_X_OUTPUT (f
)->move_offset_left
;
8524 adjusted_top
= expected_top
+ FRAME_X_OUTPUT (f
)->move_offset_top
;
8526 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8527 adjusted_left
, adjusted_top
);
8529 x_sync_with_move (f
, expected_left
, expected_top
, 0);
8532 /* It's a "Type B" window manager. We don't have to adjust the
8533 frame's position. */
8535 FRAME_DISPLAY_INFO (f
)->wm_type
= X_WMTYPE_B
;
8539 /* Wait for XGetGeometry to return up-to-date position information for a
8540 recently-moved frame. Call this immediately after calling XMoveWindow.
8541 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8542 frame has been moved to, so we use a fuzzy position comparison instead
8543 of an exact comparison. */
8546 x_sync_with_move (struct frame
*f
, int left
, int top
, int fuzzy
)
8550 while (count
++ < 50)
8552 int current_left
= 0, current_top
= 0;
8554 /* In theory, this call to XSync only needs to happen once, but in
8555 practice, it doesn't seem to work, hence the need for the surrounding
8558 XSync (FRAME_X_DISPLAY (f
), False
);
8559 x_real_positions (f
, ¤t_left
, ¤t_top
);
8563 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8566 if (eabs (current_left
- left
) <= 10
8567 && eabs (current_top
- top
) <= 40)
8570 else if (current_left
== left
&& current_top
== top
)
8574 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8575 will then return up-to-date position info. */
8577 wait_reading_process_output (0, 500000, 0, 0, Qnil
, NULL
, 0);
8581 /* Wait for an event on frame F matching EVENTTYPE. */
8583 x_wait_for_event (struct frame
*f
, int eventtype
)
8585 int level
= interrupt_input_blocked
;
8588 struct timespec tmo
, tmo_at
, time_now
;
8589 int fd
= ConnectionNumber (FRAME_X_DISPLAY (f
));
8591 f
->wait_event_type
= eventtype
;
8593 /* Set timeout to 0.1 second. Hopefully not noticeable.
8594 Maybe it should be configurable. */
8595 tmo
= make_timespec (0, 100 * 1000 * 1000);
8596 tmo_at
= timespec_add (current_timespec (), tmo
);
8598 while (f
->wait_event_type
)
8600 pending_signals
= 1;
8601 totally_unblock_input ();
8602 /* XTread_socket is called after unblock. */
8604 interrupt_input_blocked
= level
;
8609 time_now
= current_timespec ();
8610 if (timespec_cmp (tmo_at
, time_now
) < 0)
8613 tmo
= timespec_sub (tmo_at
, time_now
);
8614 if (pselect (fd
+ 1, &fds
, NULL
, NULL
, &tmo
, NULL
) == 0)
8615 break; /* Timeout */
8618 f
->wait_event_type
= 0;
8622 /* Change the size of frame F's X window to COLS/ROWS in the case F
8623 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8624 top-left-corner window gravity for this size change and subsequent
8625 size changes. Otherwise we leave the window gravity unchanged. */
8628 x_set_window_size_1 (struct frame
*f
, int change_gravity
, int width
, int height
, bool pixelwise
)
8630 int pixelwidth
, pixelheight
;
8632 check_frame_size (f
, &width
, &height
, pixelwise
);
8634 compute_fringe_widths (f
, 0);
8636 pixelwidth
= ((pixelwise
8637 ? FRAME_TEXT_TO_PIXEL_WIDTH (f
, width
)
8638 : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, width
))
8639 + FRAME_TOOLBAR_WIDTH (f
));
8640 pixelheight
= ((pixelwise
8641 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f
, height
)
8642 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, height
))
8643 + FRAME_MENUBAR_HEIGHT (f
)
8644 + FRAME_TOOLBAR_HEIGHT (f
));
8645 if (change_gravity
) f
->win_gravity
= NorthWestGravity
;
8646 x_wm_set_size_hint (f
, (long) 0, 0);
8647 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8648 pixelwidth
, pixelheight
);
8651 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8652 receive in the ConfigureNotify event; if we get what we asked
8653 for, then the event won't cause the screen to become garbaged, so
8654 we have to make sure to do it here. */
8655 SET_FRAME_GARBAGED (f
);
8657 /* Now, strictly speaking, we can't be sure that this is accurate,
8658 but the window manager will get around to dealing with the size
8659 change request eventually, and we'll hear how it went when the
8660 ConfigureNotify event gets here.
8662 We could just not bother storing any of this information here,
8663 and let the ConfigureNotify event set everything up, but that
8664 might be kind of confusing to the Lisp code, since size changes
8665 wouldn't be reported in the frame parameters until some random
8666 point in the future when the ConfigureNotify event arrives.
8668 We pass 1 for DELAY since we can't run Lisp code inside of
8671 /* But the ConfigureNotify may in fact never arrive, and then this is
8672 not right if the frame is visible. Instead wait (with timeout)
8673 for the ConfigureNotify. */
8674 if (FRAME_VISIBLE_P (f
))
8675 x_wait_for_event (f
, ConfigureNotify
);
8678 change_frame_size (f
, width
, height
, 0, 1, 0, 1);
8684 /* Call this to change the size of frame F's x-window.
8685 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8686 for this size change and subsequent size changes.
8687 Otherwise we leave the window gravity unchanged. */
8690 x_set_window_size (struct frame
*f
, int change_gravity
, int width
, int height
, bool pixelwise
)
8694 check_frame_size (f
, &width
, &height
, pixelwise
);
8696 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
8698 int text_width
, text_height
;
8700 /* When the frame is maximized/fullscreen or running under for
8701 example Xmonad, x_set_window_size_1 will be a no-op.
8702 In that case, the right thing to do is extend rows/width to
8703 the current frame size. We do that first if x_set_window_size_1
8704 turns out to not be a no-op (there is no way to know).
8705 The size will be adjusted again if the frame gets a
8706 ConfigureNotify event as a result of x_set_window_size. */
8707 int pixelh
= FRAME_PIXEL_HEIGHT (f
);
8708 #ifdef USE_X_TOOLKIT
8709 /* The menu bar is not part of text lines. The tool bar
8711 pixelh
-= FRAME_MENUBAR_HEIGHT (f
);
8713 text_width
= FRAME_PIXEL_TO_TEXT_WIDTH (f
, FRAME_PIXEL_WIDTH (f
));
8714 text_height
= FRAME_PIXEL_TO_TEXT_HEIGHT (f
, pixelh
);
8716 change_frame_size (f
, text_width
, text_height
, 0, 1, 0, 1);
8720 if (FRAME_GTK_WIDGET (f
))
8722 xg_frame_set_char_size (f
, width
* FRAME_COLUMN_WIDTH (f
),
8723 height
* FRAME_LINE_HEIGHT (f
));
8725 xg_frame_set_char_size (f
, width
, height
);
8727 x_set_window_size_1 (f
, change_gravity
, width
, height
, pixelwise
);
8728 #else /* not USE_GTK */
8730 x_set_window_size_1 (f
, change_gravity
, width
, height
, pixelwise
);
8731 #if !defined USE_X_TOOLKIT
8732 x_clear_under_internal_border (f
);
8735 #endif /* not USE_GTK */
8737 /* If cursor was outside the new size, mark it as off. */
8738 mark_window_cursors_off (XWINDOW (f
->root_window
));
8740 /* Clear out any recollection of where the mouse highlighting was,
8741 since it might be in a place that's outside the new frame size.
8742 Actually checking whether it is outside is a pain in the neck,
8743 so don't try--just let the highlighting be done afresh with new size. */
8744 cancel_mouse_face (f
);
8749 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8752 frame_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
)
8756 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
8757 0, 0, 0, 0, pix_x
, pix_y
);
8761 /* Raise frame F. */
8764 x_raise_frame (struct frame
*f
)
8767 if (FRAME_VISIBLE_P (f
))
8768 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8769 XFlush (FRAME_X_DISPLAY (f
));
8773 /* Lower frame F. */
8776 x_lower_frame (struct frame
*f
)
8778 if (FRAME_VISIBLE_P (f
))
8781 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
));
8782 XFlush (FRAME_X_DISPLAY (f
));
8787 /* Request focus with XEmbed */
8790 xembed_request_focus (struct frame
*f
)
8792 /* See XEmbed Protocol Specification at
8793 http://freedesktop.org/wiki/Specifications/xembed-spec */
8794 if (FRAME_VISIBLE_P (f
))
8795 xembed_send_message (f
, CurrentTime
,
8796 XEMBED_REQUEST_FOCUS
, 0, 0, 0);
8799 /* Activate frame with Extended Window Manager Hints */
8802 x_ewmh_activate_frame (struct frame
*f
)
8804 /* See Window Manager Specification/Extended Window Manager Hints at
8805 http://freedesktop.org/wiki/Specifications/wm-spec */
8807 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8809 if (FRAME_VISIBLE_P (f
) && wm_supports (f
, dpyinfo
->Xatom_net_active_window
))
8812 XSETFRAME (frame
, f
);
8813 x_send_client_event (frame
, make_number (0), frame
,
8814 dpyinfo
->Xatom_net_active_window
,
8816 list2i (1, dpyinfo
->last_user_time
));
8821 XTframe_raise_lower (struct frame
*f
, int raise_flag
)
8829 /* XEmbed implementation. */
8831 #if defined USE_X_TOOLKIT || ! defined USE_GTK
8833 /* XEmbed implementation. */
8835 #define XEMBED_VERSION 0
8838 xembed_set_info (struct frame
*f
, enum xembed_info flags
)
8840 unsigned long data
[2];
8841 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
8843 data
[0] = XEMBED_VERSION
;
8846 XChangeProperty (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8847 dpyinfo
->Xatom_XEMBED_INFO
, dpyinfo
->Xatom_XEMBED_INFO
,
8848 32, PropModeReplace
, (unsigned char *) data
, 2);
8850 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
8853 xembed_send_message (struct frame
*f
, Time t
, enum xembed_message msg
,
8854 long int detail
, long int data1
, long int data2
)
8858 event
.xclient
.type
= ClientMessage
;
8859 event
.xclient
.window
= FRAME_X_OUTPUT (f
)->parent_desc
;
8860 event
.xclient
.message_type
= FRAME_DISPLAY_INFO (f
)->Xatom_XEMBED
;
8861 event
.xclient
.format
= 32;
8862 event
.xclient
.data
.l
[0] = t
;
8863 event
.xclient
.data
.l
[1] = msg
;
8864 event
.xclient
.data
.l
[2] = detail
;
8865 event
.xclient
.data
.l
[3] = data1
;
8866 event
.xclient
.data
.l
[4] = data2
;
8868 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_OUTPUT (f
)->parent_desc
,
8869 False
, NoEventMask
, &event
);
8870 XSync (FRAME_X_DISPLAY (f
), False
);
8873 /* Change of visibility. */
8875 /* This tries to wait until the frame is really visible.
8876 However, if the window manager asks the user where to position
8877 the frame, this will return before the user finishes doing that.
8878 The frame will not actually be visible at that time,
8879 but it will become visible later when the window manager
8880 finishes with it. */
8883 x_make_frame_visible (struct frame
*f
)
8885 int original_top
, original_left
;
8890 x_set_bitmap_icon (f
);
8892 if (! FRAME_VISIBLE_P (f
))
8894 /* We test FRAME_GARBAGED_P here to make sure we don't
8895 call x_set_offset a second time
8896 if we get to x_make_frame_visible a second time
8897 before the window gets really visible. */
8898 if (! FRAME_ICONIFIED_P (f
)
8899 && ! FRAME_X_EMBEDDED_P (f
)
8900 && ! f
->output_data
.x
->asked_for_visible
)
8901 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
8903 f
->output_data
.x
->asked_for_visible
= 1;
8905 if (! EQ (Vx_no_window_manager
, Qt
))
8906 x_wm_set_window_state (f
, NormalState
);
8907 #ifdef USE_X_TOOLKIT
8908 if (FRAME_X_EMBEDDED_P (f
))
8909 xembed_set_info (f
, XEMBED_MAPPED
);
8912 /* This was XtPopup, but that did nothing for an iconified frame. */
8913 XtMapWidget (f
->output_data
.x
->widget
);
8915 #else /* not USE_X_TOOLKIT */
8917 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
8918 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
8920 if (FRAME_X_EMBEDDED_P (f
))
8921 xembed_set_info (f
, XEMBED_MAPPED
);
8923 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
8924 #endif /* not USE_GTK */
8925 #endif /* not USE_X_TOOLKIT */
8928 XFlush (FRAME_X_DISPLAY (f
));
8930 /* Synchronize to ensure Emacs knows the frame is visible
8931 before we do anything else. We do this loop with input not blocked
8932 so that incoming events are handled. */
8935 /* This must be before UNBLOCK_INPUT
8936 since events that arrive in response to the actions above
8937 will set it when they are handled. */
8938 int previously_visible
= f
->output_data
.x
->has_been_visible
;
8940 original_left
= f
->left_pos
;
8941 original_top
= f
->top_pos
;
8943 /* This must come after we set COUNT. */
8946 /* We unblock here so that arriving X events are processed. */
8948 /* Now move the window back to where it was "supposed to be".
8949 But don't do it if the gravity is negative.
8950 When the gravity is negative, this uses a position
8951 that is 3 pixels too low. Perhaps that's really the border width.
8953 Don't do this if the window has never been visible before,
8954 because the window manager may choose the position
8955 and we don't want to override it. */
8957 if (! FRAME_VISIBLE_P (f
)
8958 && ! FRAME_ICONIFIED_P (f
)
8959 && ! FRAME_X_EMBEDDED_P (f
)
8960 && f
->win_gravity
== NorthWestGravity
8961 && previously_visible
)
8965 unsigned int width
, height
, border
, depth
;
8969 /* On some window managers (such as FVWM) moving an existing
8970 window, even to the same place, causes the window manager
8971 to introduce an offset. This can cause the window to move
8972 to an unexpected location. Check the geometry (a little
8973 slow here) and then verify that the window is in the right
8974 place. If the window is not in the right place, move it
8975 there, and take the potential window manager hit. */
8976 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8977 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
8979 if (original_left
!= x
|| original_top
!= y
)
8980 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
8981 original_left
, original_top
);
8986 XSETFRAME (frame
, f
);
8988 /* Process X events until a MapNotify event has been seen. */
8989 while (!FRAME_VISIBLE_P (f
))
8991 /* Force processing of queued events. */
8994 /* If on another desktop, the deiconify/map may be ignored and the
8995 frame never becomes visible. XMonad does this.
8996 Prevent an endless loop. */
8997 if (FRAME_ICONIFIED_P (f
) && ++tries
> 100)
9000 /* This hack is still in use at least for Cygwin. See
9001 http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html.
9003 Machines that do polling rather than SIGIO have been
9004 observed to go into a busy-wait here. So we'll fake an
9005 alarm signal to let the handler know that there's something
9006 to be read. We used to raise a real alarm, but it seems
9007 that the handler isn't always enabled here. This is
9009 if (input_polling_used ())
9011 /* It could be confusing if a real alarm arrives while
9012 processing the fake one. Turn it off and let the
9013 handler reset it. */
9014 int old_poll_suppress_count
= poll_suppress_count
;
9015 poll_suppress_count
= 1;
9016 poll_for_input_1 ();
9017 poll_suppress_count
= old_poll_suppress_count
;
9020 if (XPending (FRAME_X_DISPLAY (f
)))
9023 XNextEvent (FRAME_X_DISPLAY (f
), &xev
);
9024 x_dispatch_event (&xev
, FRAME_X_DISPLAY (f
));
9030 /* Change from mapped state to withdrawn state. */
9032 /* Make the frame visible (mapped and not iconified). */
9035 x_make_frame_invisible (struct frame
*f
)
9039 /* Use the frame's outermost window, not the one we normally draw on. */
9040 window
= FRAME_OUTER_WINDOW (f
);
9042 /* Don't keep the highlight on an invisible frame. */
9043 if (FRAME_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9044 FRAME_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9048 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9049 that the current position of the window is user-specified, rather than
9050 program-specified, so that when the window is mapped again, it will be
9051 placed at the same location, without forcing the user to position it
9052 by hand again (they have already done that once for this window.) */
9053 x_wm_set_size_hint (f
, (long) 0, 1);
9056 if (FRAME_GTK_OUTER_WIDGET (f
))
9057 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f
));
9060 if (FRAME_X_EMBEDDED_P (f
))
9061 xembed_set_info (f
, 0);
9066 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
9067 DefaultScreen (FRAME_X_DISPLAY (f
))))
9070 error ("Can't notify window manager of window withdrawal");
9074 /* We can't distinguish this from iconification
9075 just by the event that we get from the server.
9076 So we can't win using the usual strategy of letting
9077 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9078 and synchronize with the server to make sure we agree. */
9079 SET_FRAME_VISIBLE (f
, 0);
9080 SET_FRAME_ICONIFIED (f
, 0);
9087 /* Change window state from mapped to iconified. */
9090 x_iconify_frame (struct frame
*f
)
9092 #ifdef USE_X_TOOLKIT
9096 /* Don't keep the highlight on an invisible frame. */
9097 if (FRAME_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
9098 FRAME_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
9100 if (FRAME_ICONIFIED_P (f
))
9105 x_set_bitmap_icon (f
);
9107 #if defined (USE_GTK)
9108 if (FRAME_GTK_OUTER_WIDGET (f
))
9110 if (! FRAME_VISIBLE_P (f
))
9111 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f
));
9113 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
9114 SET_FRAME_VISIBLE (f
, 0);
9115 SET_FRAME_ICONIFIED (f
, 1);
9121 #ifdef USE_X_TOOLKIT
9123 if (! FRAME_VISIBLE_P (f
))
9125 if (! EQ (Vx_no_window_manager
, Qt
))
9126 x_wm_set_window_state (f
, IconicState
);
9127 /* This was XtPopup, but that did nothing for an iconified frame. */
9128 XtMapWidget (f
->output_data
.x
->widget
);
9129 /* The server won't give us any event to indicate
9130 that an invisible frame was changed to an icon,
9131 so we have to record it here. */
9132 SET_FRAME_VISIBLE (f
, 0);
9133 SET_FRAME_ICONIFIED (f
, 1);
9138 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
9139 XtWindow (f
->output_data
.x
->widget
),
9140 DefaultScreen (FRAME_X_DISPLAY (f
)));
9144 error ("Can't notify window manager of iconification");
9146 SET_FRAME_ICONIFIED (f
, 1);
9147 SET_FRAME_VISIBLE (f
, 0);
9150 XFlush (FRAME_X_DISPLAY (f
));
9152 #else /* not USE_X_TOOLKIT */
9154 /* Make sure the X server knows where the window should be positioned,
9155 in case the user deiconifies with the window manager. */
9156 if (! FRAME_VISIBLE_P (f
)
9157 && ! FRAME_ICONIFIED_P (f
)
9158 && ! FRAME_X_EMBEDDED_P (f
))
9159 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
9161 /* Since we don't know which revision of X we're running, we'll use both
9162 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9164 /* X11R4: send a ClientMessage to the window manager using the
9165 WM_CHANGE_STATE type. */
9169 msg
.xclient
.window
= FRAME_X_WINDOW (f
);
9170 msg
.xclient
.type
= ClientMessage
;
9171 msg
.xclient
.message_type
= FRAME_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
9172 msg
.xclient
.format
= 32;
9173 msg
.xclient
.data
.l
[0] = IconicState
;
9175 if (! XSendEvent (FRAME_X_DISPLAY (f
),
9176 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
9178 SubstructureRedirectMask
| SubstructureNotifyMask
,
9182 error ("Can't notify window manager of iconification");
9186 /* X11R3: set the initial_state field of the window manager hints to
9188 x_wm_set_window_state (f
, IconicState
);
9190 if (!FRAME_VISIBLE_P (f
))
9192 /* If the frame was withdrawn, before, we must map it. */
9193 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9196 SET_FRAME_ICONIFIED (f
, 1);
9197 SET_FRAME_VISIBLE (f
, 0);
9199 XFlush (FRAME_X_DISPLAY (f
));
9201 #endif /* not USE_X_TOOLKIT */
9205 /* Free X resources of frame F. */
9208 x_free_frame_resources (struct frame
*f
)
9210 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
9211 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
9212 #ifdef USE_X_TOOLKIT
9214 struct scroll_bar
*b
;
9219 /* If a display connection is dead, don't try sending more
9220 commands to the X server. */
9221 if (dpyinfo
->display
)
9223 /* Always exit with visible pointer to avoid weird issue
9224 with Xfixes (Bug#17609). */
9225 if (f
->pointer_invisible
)
9226 FRAME_DISPLAY_INFO (f
)->toggle_visible_pointer (f
, 0);
9228 /* We must free faces before destroying windows because some
9229 font-driver (e.g. xft) access a window while finishing a
9231 free_frame_faces (f
);
9233 if (f
->output_data
.x
->icon_desc
)
9234 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
9236 #ifdef USE_X_TOOLKIT
9237 /* Explicitly destroy the scroll bars of the frame. Without
9238 this, we get "BadDrawable" errors from the toolkit later on,
9239 presumably from expose events generated for the disappearing
9240 toolkit scroll bars. */
9241 for (bar
= FRAME_SCROLL_BARS (f
); !NILP (bar
); bar
= b
->next
)
9243 b
= XSCROLL_BAR (bar
);
9244 x_scroll_bar_remove (b
);
9253 #ifdef USE_X_TOOLKIT
9254 if (f
->output_data
.x
->widget
)
9256 XtDestroyWidget (f
->output_data
.x
->widget
);
9257 f
->output_data
.x
->widget
= NULL
;
9259 /* Tooltips don't have widgets, only a simple X window, even if
9260 we are using a toolkit. */
9261 else if (FRAME_X_WINDOW (f
))
9262 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9264 free_frame_menubar (f
);
9265 #else /* !USE_X_TOOLKIT */
9268 xg_free_frame_widgets (f
);
9269 #endif /* USE_GTK */
9271 if (FRAME_X_WINDOW (f
))
9272 XDestroyWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9273 #endif /* !USE_X_TOOLKIT */
9275 unload_color (f
, FRAME_FOREGROUND_PIXEL (f
));
9276 unload_color (f
, FRAME_BACKGROUND_PIXEL (f
));
9277 unload_color (f
, f
->output_data
.x
->cursor_pixel
);
9278 unload_color (f
, f
->output_data
.x
->cursor_foreground_pixel
);
9279 unload_color (f
, f
->output_data
.x
->border_pixel
);
9280 unload_color (f
, f
->output_data
.x
->mouse_pixel
);
9282 if (f
->output_data
.x
->scroll_bar_background_pixel
!= -1)
9283 unload_color (f
, f
->output_data
.x
->scroll_bar_background_pixel
);
9284 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
9285 unload_color (f
, f
->output_data
.x
->scroll_bar_foreground_pixel
);
9286 #ifdef USE_TOOLKIT_SCROLL_BARS
9287 /* Scrollbar shadow colors. */
9288 if (f
->output_data
.x
->scroll_bar_top_shadow_pixel
!= -1)
9289 unload_color (f
, f
->output_data
.x
->scroll_bar_top_shadow_pixel
);
9290 if (f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
!= -1)
9291 unload_color (f
, f
->output_data
.x
->scroll_bar_bottom_shadow_pixel
);
9292 #endif /* USE_TOOLKIT_SCROLL_BARS */
9293 if (f
->output_data
.x
->white_relief
.pixel
!= -1)
9294 unload_color (f
, f
->output_data
.x
->white_relief
.pixel
);
9295 if (f
->output_data
.x
->black_relief
.pixel
!= -1)
9296 unload_color (f
, f
->output_data
.x
->black_relief
.pixel
);
9300 /* Free extra GCs allocated by x_setup_relief_colors. */
9301 if (f
->output_data
.x
->white_relief
.gc
)
9303 XFreeGC (dpyinfo
->display
, f
->output_data
.x
->white_relief
.gc
);
9304 f
->output_data
.x
->white_relief
.gc
= 0;
9306 if (f
->output_data
.x
->black_relief
.gc
)
9308 XFreeGC (dpyinfo
->display
, f
->output_data
.x
->black_relief
.gc
);
9309 f
->output_data
.x
->black_relief
.gc
= 0;
9313 if (f
->output_data
.x
->text_cursor
!= 0)
9314 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->text_cursor
);
9315 if (f
->output_data
.x
->nontext_cursor
!= 0)
9316 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->nontext_cursor
);
9317 if (f
->output_data
.x
->modeline_cursor
!= 0)
9318 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->modeline_cursor
);
9319 if (f
->output_data
.x
->hand_cursor
!= 0)
9320 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->hand_cursor
);
9321 if (f
->output_data
.x
->hourglass_cursor
!= 0)
9322 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->hourglass_cursor
);
9323 if (f
->output_data
.x
->horizontal_drag_cursor
!= 0)
9324 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->horizontal_drag_cursor
);
9325 if (f
->output_data
.x
->vertical_drag_cursor
!= 0)
9326 XFreeCursor (FRAME_X_DISPLAY (f
), f
->output_data
.x
->vertical_drag_cursor
);
9328 XFlush (FRAME_X_DISPLAY (f
));
9331 xfree (f
->output_data
.x
->saved_menu_event
);
9332 xfree (f
->output_data
.x
);
9333 f
->output_data
.x
= NULL
;
9335 if (f
== dpyinfo
->x_focus_frame
)
9336 dpyinfo
->x_focus_frame
= 0;
9337 if (f
== dpyinfo
->x_focus_event_frame
)
9338 dpyinfo
->x_focus_event_frame
= 0;
9339 if (f
== dpyinfo
->x_highlight_frame
)
9340 dpyinfo
->x_highlight_frame
= 0;
9341 if (f
== hlinfo
->mouse_face_mouse_frame
)
9342 reset_mouse_highlight (hlinfo
);
9348 /* Destroy the X window of frame F. */
9351 x_destroy_window (struct frame
*f
)
9353 struct x_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
9355 /* If a display connection is dead, don't try sending more
9356 commands to the X server. */
9357 if (dpyinfo
->display
!= 0)
9358 x_free_frame_resources (f
);
9360 dpyinfo
->reference_count
--;
9364 /* Setting window manager hints. */
9366 /* Set the normal size hints for the window manager, for frame F.
9367 FLAGS is the flags word to use--or 0 meaning preserve the flags
9368 that the window now has.
9369 If USER_POSITION, set the USPosition
9370 flag (this is useful when FLAGS is 0).
9371 The GTK version is in gtkutils.c. */
9375 x_wm_set_size_hint (struct frame
*f
, long flags
, bool user_position
)
9377 XSizeHints size_hints
;
9378 Window window
= FRAME_OUTER_WINDOW (f
);
9380 #ifdef USE_X_TOOLKIT
9381 if (f
->output_data
.x
->widget
)
9383 widget_update_wm_size_hints (f
->output_data
.x
->widget
);
9388 /* Setting PMaxSize caused various problems. */
9389 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
9391 size_hints
.x
= f
->left_pos
;
9392 size_hints
.y
= f
->top_pos
;
9394 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
9395 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
9397 size_hints
.width_inc
= frame_resize_pixelwise
? 1 : FRAME_COLUMN_WIDTH (f
);
9398 size_hints
.height_inc
= frame_resize_pixelwise
? 1 : FRAME_LINE_HEIGHT (f
);
9400 size_hints
.max_width
= x_display_pixel_width (FRAME_DISPLAY_INFO (f
))
9401 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9402 size_hints
.max_height
= x_display_pixel_height (FRAME_DISPLAY_INFO (f
))
9403 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9405 /* Calculate the base and minimum sizes. */
9407 int base_width
, base_height
;
9408 int min_rows
= 0, min_cols
= 0;
9410 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
9411 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
9413 check_frame_size (f
, &min_cols
, &min_rows
, 0);
9415 if (frame_resize_pixelwise
)
9416 /* Needed to prevent a bad protocol error crash when making the
9417 frame size very small. */
9419 min_cols
= 2 * min_cols
;
9420 min_rows
= 2 * min_rows
;
9423 /* The window manager uses the base width hints to calculate the
9424 current number of rows and columns in the frame while
9425 resizing; min_width and min_height aren't useful for this
9426 purpose, since they might not give the dimensions for a
9427 zero-row, zero-column frame.
9429 We use the base_width and base_height members if we have
9430 them; otherwise, we set the min_width and min_height members
9431 to the size for a zero x zero frame. */
9433 size_hints
.flags
|= PBaseSize
;
9434 size_hints
.base_width
= base_width
;
9435 size_hints
.base_height
= base_height
+ FRAME_MENUBAR_HEIGHT (f
);
9436 size_hints
.min_width
= base_width
+ min_cols
* FRAME_COLUMN_WIDTH (f
);
9437 size_hints
.min_height
= base_height
+ min_rows
* FRAME_LINE_HEIGHT (f
);
9440 /* If we don't need the old flags, we don't need the old hint at all. */
9443 size_hints
.flags
|= flags
;
9448 XSizeHints hints
; /* Sometimes I hate X Windows... */
9449 long supplied_return
;
9452 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
9456 size_hints
.flags
|= flags
;
9461 if (hints
.flags
& PSize
)
9462 size_hints
.flags
|= PSize
;
9463 if (hints
.flags
& PPosition
)
9464 size_hints
.flags
|= PPosition
;
9465 if (hints
.flags
& USPosition
)
9466 size_hints
.flags
|= USPosition
;
9467 if (hints
.flags
& USSize
)
9468 size_hints
.flags
|= USSize
;
9475 size_hints
.win_gravity
= f
->win_gravity
;
9476 size_hints
.flags
|= PWinGravity
;
9480 size_hints
.flags
&= ~ PPosition
;
9481 size_hints
.flags
|= USPosition
;
9483 #endif /* PWinGravity */
9485 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
9487 #endif /* not USE_GTK */
9489 /* Used for IconicState or NormalState */
9492 x_wm_set_window_state (struct frame
*f
, int state
)
9494 #ifdef USE_X_TOOLKIT
9497 XtSetArg (al
[0], XtNinitialState
, state
);
9498 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9499 #else /* not USE_X_TOOLKIT */
9500 Window window
= FRAME_X_WINDOW (f
);
9502 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
9503 f
->output_data
.x
->wm_hints
.initial_state
= state
;
9505 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9506 #endif /* not USE_X_TOOLKIT */
9510 x_wm_set_icon_pixmap (struct frame
*f
, ptrdiff_t pixmap_id
)
9512 Pixmap icon_pixmap
, icon_mask
;
9514 #if !defined USE_X_TOOLKIT && !defined USE_GTK
9515 Window window
= FRAME_OUTER_WINDOW (f
);
9520 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
9521 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
9522 icon_mask
= x_bitmap_mask (f
, pixmap_id
);
9523 f
->output_data
.x
->wm_hints
.icon_mask
= icon_mask
;
9527 /* It seems there is no way to turn off use of an icon
9535 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
);
9539 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9543 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
9544 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9545 XtSetArg (al
[0], XtNiconMask
, icon_mask
);
9546 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
9549 #else /* not USE_X_TOOLKIT && not USE_GTK */
9551 f
->output_data
.x
->wm_hints
.flags
|= (IconPixmapHint
| IconMaskHint
);
9552 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9554 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9558 x_wm_set_icon_position (struct frame
*f
, int icon_x
, int icon_y
)
9560 Window window
= FRAME_OUTER_WINDOW (f
);
9562 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
9563 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
9564 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
9566 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
9570 /***********************************************************************
9572 ***********************************************************************/
9576 /* Check that FONT is valid on frame F. It is if it can be found in F's
9580 x_check_font (struct frame
*f
, struct font
*font
)
9582 eassert (font
!= NULL
&& ! NILP (font
->props
[FONT_TYPE_INDEX
]));
9583 if (font
->driver
->check
)
9584 eassert (font
->driver
->check (f
, font
) == 0);
9587 #endif /* GLYPH_DEBUG */
9590 /***********************************************************************
9592 ***********************************************************************/
9594 #ifdef USE_X_TOOLKIT
9595 static XrmOptionDescRec emacs_options
[] = {
9596 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
9597 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
9599 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9600 XrmoptionSepArg
, NULL
},
9601 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
9603 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9604 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9605 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
9606 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
9607 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
9608 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
9609 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
9612 /* Whether atimer for Xt timeouts is activated or not. */
9614 static int x_timeout_atimer_activated_flag
;
9616 #endif /* USE_X_TOOLKIT */
9618 static int x_initialized
;
9620 /* Test whether two display-name strings agree up to the dot that separates
9621 the screen number from the server number. */
9623 same_x_server (const char *name1
, const char *name2
)
9626 const char *system_name
= SSDATA (Vsystem_name
);
9627 ptrdiff_t system_name_length
= SBYTES (Vsystem_name
);
9628 ptrdiff_t length_until_period
= 0;
9630 while (system_name
[length_until_period
] != 0
9631 && system_name
[length_until_period
] != '.')
9632 length_until_period
++;
9634 /* Treat `unix' like an empty host name. */
9635 if (! strncmp (name1
, "unix:", 5))
9637 if (! strncmp (name2
, "unix:", 5))
9639 /* Treat this host's name like an empty host name. */
9640 if (! strncmp (name1
, system_name
, system_name_length
)
9641 && name1
[system_name_length
] == ':')
9642 name1
+= system_name_length
;
9643 if (! strncmp (name2
, system_name
, system_name_length
)
9644 && name2
[system_name_length
] == ':')
9645 name2
+= system_name_length
;
9646 /* Treat this host's domainless name like an empty host name. */
9647 if (! strncmp (name1
, system_name
, length_until_period
)
9648 && name1
[length_until_period
] == ':')
9649 name1
+= length_until_period
;
9650 if (! strncmp (name2
, system_name
, length_until_period
)
9651 && name2
[length_until_period
] == ':')
9652 name2
+= length_until_period
;
9654 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
9658 if (seen_colon
&& *name1
== '.')
9662 && (*name1
== '.' || *name1
== '\0')
9663 && (*name2
== '.' || *name2
== '\0'));
9666 /* Count number of set bits in mask and number of bits to shift to
9667 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9670 get_bits_and_offset (unsigned long mask
, int *bits
, int *offset
)
9691 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9692 But don't permanently open it, just test its availability. */
9695 x_display_ok (const char *display
)
9697 Display
*dpy
= XOpenDisplay (display
);
9698 return dpy
? (XCloseDisplay (dpy
), 1) : 0;
9703 my_log_handler (const gchar
*log_domain
, GLogLevelFlags log_level
,
9704 const gchar
*msg
, gpointer user_data
)
9706 if (!strstr (msg
, "g_set_prgname"))
9707 fprintf (stderr
, "%s-WARNING **: %s\n", log_domain
, msg
);
9711 /* Create invisible cursor on X display referred by DPYINFO. */
9714 make_invisible_cursor (struct x_display_info
*dpyinfo
)
9716 Display
*dpy
= dpyinfo
->display
;
9717 static char const no_data
[] = { 0 };
9722 x_catch_errors (dpy
);
9723 pix
= XCreateBitmapFromData (dpy
, dpyinfo
->root_window
, no_data
, 1, 1);
9724 if (! x_had_errors_p (dpy
) && pix
!= None
)
9728 col
.red
= col
.green
= col
.blue
= 0;
9729 col
.flags
= DoRed
| DoGreen
| DoBlue
;
9730 pixc
= XCreatePixmapCursor (dpy
, pix
, pix
, &col
, &col
, 0, 0);
9731 if (! x_had_errors_p (dpy
) && pixc
!= None
)
9733 XFreePixmap (dpy
, pix
);
9736 x_uncatch_errors ();
9741 /* True if DPY supports Xfixes extension >= 4. */
9744 x_probe_xfixes_extension (Display
*dpy
)
9748 return XFixesQueryVersion (dpy
, &major
, &minor
) && major
>= 4;
9751 #endif /* HAVE_XFIXES */
9754 /* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
9757 xfixes_toggle_visible_pointer (struct frame
*f
, bool invisible
)
9761 XFixesHideCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9763 XFixesShowCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
9764 f
->pointer_invisible
= invisible
;
9767 #endif /* HAVE_XFIXES */
9770 /* Toggle mouse pointer visibility on frame F by using invisible cursor. */
9773 x_toggle_visible_pointer (struct frame
*f
, bool invisible
)
9775 eassert (FRAME_DISPLAY_INFO (f
)->invisible_cursor
!= 0);
9777 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9778 FRAME_DISPLAY_INFO (f
)->invisible_cursor
);
9780 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9781 f
->output_data
.x
->current_cursor
);
9782 f
->pointer_invisible
= invisible
;
9785 /* Setup pointer blanking, prefer Xfixes if available. */
9788 x_setup_pointer_blanking (struct x_display_info
*dpyinfo
)
9790 /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
9791 X server bug, see http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */
9792 if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo
->display
))
9793 dpyinfo
->toggle_visible_pointer
= xfixes_toggle_visible_pointer
;
9796 dpyinfo
->toggle_visible_pointer
= x_toggle_visible_pointer
;
9797 dpyinfo
->invisible_cursor
= make_invisible_cursor (dpyinfo
);
9801 /* Current X display connection identifier. Incremented for each next
9802 connection established. */
9803 static unsigned x_display_id
;
9805 /* Open a connection to X display DISPLAY_NAME, and return
9806 the structure that describes the open display.
9807 If we cannot contact the display, return null. */
9809 struct x_display_info
*
9810 x_term_init (Lisp_Object display_name
, char *xrm_option
, char *resource_name
)
9814 struct terminal
*terminal
;
9815 struct x_display_info
*dpyinfo
;
9827 if (! x_display_ok (SSDATA (display_name
)))
9828 error ("Display %s can't be opened", SSDATA (display_name
));
9834 char *argv
[NUM_ARGV
];
9835 char **argv2
= argv
;
9838 if (x_initialized
++ > 1)
9840 xg_display_open (SSDATA (display_name
), &dpy
);
9844 static char display_opt
[] = "--display";
9845 static char name_opt
[] = "--name";
9847 for (argc
= 0; argc
< NUM_ARGV
; ++argc
)
9851 argv
[argc
++] = initial_argv
[0];
9853 if (! NILP (display_name
))
9855 argv
[argc
++] = display_opt
;
9856 argv
[argc
++] = SSDATA (display_name
);
9859 argv
[argc
++] = name_opt
;
9860 argv
[argc
++] = resource_name
;
9862 XSetLocaleModifiers ("");
9864 /* Emacs can only handle core input events, so make sure
9865 Gtk doesn't use Xinput or Xinput2 extensions. */
9866 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
9868 /* Work around GLib bug that outputs a faulty warning. See
9869 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
9870 id
= g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING
| G_LOG_FLAG_FATAL
9871 | G_LOG_FLAG_RECURSION
, my_log_handler
, NULL
);
9873 /* NULL window -> events for all windows go to our function.
9874 Call before gtk_init so Gtk+ event filters comes after our. */
9875 gdk_window_add_filter (NULL
, event_handler_gdk
, NULL
);
9877 /* gtk_init does set_locale. Fix locale before and after. */
9879 gtk_init (&argc
, &argv2
);
9882 g_log_remove_handler ("GLib", id
);
9886 dpy
= DEFAULT_GDK_DISPLAY ();
9888 #if ! GTK_CHECK_VERSION (2, 90, 0)
9889 /* Load our own gtkrc if it exists. */
9891 const char *file
= "~/.emacs.d/gtkrc";
9892 Lisp_Object s
, abs_file
;
9894 s
= build_string (file
);
9895 abs_file
= Fexpand_file_name (s
, Qnil
);
9897 if (! NILP (abs_file
) && !NILP (Ffile_readable_p (abs_file
)))
9898 gtk_rc_parse (SSDATA (abs_file
));
9902 XSetErrorHandler (x_error_handler
);
9903 XSetIOErrorHandler (x_io_error_quitter
);
9906 #else /* not USE_GTK */
9907 #ifdef USE_X_TOOLKIT
9908 /* weiner@footloose.sps.mot.com reports that this causes
9910 X protocol error: BadAtom (invalid Atom parameter)
9911 on protocol request 18skiloaf.
9912 So let's not use it until R6. */
9914 XtSetLanguageProc (NULL
, NULL
, NULL
);
9925 argv
[argc
++] = "-xrm";
9926 argv
[argc
++] = xrm_option
;
9928 turn_on_atimers (0);
9929 dpy
= XtOpenDisplay (Xt_app_con
, SSDATA (display_name
),
9930 resource_name
, EMACS_CLASS
,
9931 emacs_options
, XtNumber (emacs_options
),
9933 turn_on_atimers (1);
9936 /* I think this is to compensate for XtSetLanguageProc. */
9941 #else /* not USE_X_TOOLKIT */
9942 XSetLocaleModifiers ("");
9943 dpy
= XOpenDisplay (SSDATA (display_name
));
9944 #endif /* not USE_X_TOOLKIT */
9945 #endif /* not USE_GTK*/
9947 /* Detect failure. */
9954 /* We have definitely succeeded. Record the new connection. */
9956 dpyinfo
= xzalloc (sizeof *dpyinfo
);
9957 terminal
= x_create_terminal (dpyinfo
);
9960 struct x_display_info
*share
;
9962 for (share
= x_display_list
; share
; share
= share
->next
)
9963 if (same_x_server (SSDATA (XCAR (share
->name_list_element
)),
9964 SSDATA (display_name
)))
9967 terminal
->kboard
= share
->terminal
->kboard
;
9970 terminal
->kboard
= allocate_kboard (Qx
);
9972 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
9974 char *vendor
= ServerVendor (dpy
);
9976 /* Protect terminal from GC before removing it from the
9977 list of terminals. */
9978 struct gcpro gcpro1
;
9979 Lisp_Object gcpro_term
;
9980 XSETTERMINAL (gcpro_term
, terminal
);
9981 GCPRO1 (gcpro_term
);
9983 /* Temporarily hide the partially initialized terminal. */
9984 terminal_list
= terminal
->next_terminal
;
9986 kset_system_key_alist
9988 call1 (Qvendor_specific_keysyms
,
9989 vendor
? build_string (vendor
) : empty_unibyte_string
));
9991 terminal
->next_terminal
= terminal_list
;
9992 terminal_list
= terminal
;
9996 /* Don't let the initial kboard remain current longer than necessary.
9997 That would cause problems if a file loaded on startup tries to
9998 prompt in the mini-buffer. */
9999 if (current_kboard
== initial_kboard
)
10000 current_kboard
= terminal
->kboard
;
10002 terminal
->kboard
->reference_count
++;
10005 /* Put this display on the chain. */
10006 dpyinfo
->next
= x_display_list
;
10007 x_display_list
= dpyinfo
;
10009 dpyinfo
->name_list_element
= Fcons (display_name
, Qnil
);
10010 dpyinfo
->display
= dpy
;
10012 /* Set the name of the terminal. */
10013 terminal
->name
= xlispstrdup (display_name
);
10016 XSetAfterFunction (x_current_display
, x_trace_wire
);
10019 lim
= min (PTRDIFF_MAX
, SIZE_MAX
) - sizeof "@";
10020 if (lim
- SBYTES (Vinvocation_name
) < SBYTES (Vsystem_name
))
10021 memory_full (SIZE_MAX
);
10022 dpyinfo
->x_id
= ++x_display_id
;
10023 dpyinfo
->x_id_name
= xmalloc (SBYTES (Vinvocation_name
)
10024 + SBYTES (Vsystem_name
) + 2);
10025 strcat (strcat (strcpy (dpyinfo
->x_id_name
, SSDATA (Vinvocation_name
)), "@"),
10026 SSDATA (Vsystem_name
));
10028 /* Figure out which modifier bits mean what. */
10029 x_find_modifier_meanings (dpyinfo
);
10031 /* Get the scroll bar cursor. */
10033 /* We must create a GTK cursor, it is required for GTK widgets. */
10034 dpyinfo
->xg_cursor
= xg_create_default_cursor (dpyinfo
->display
);
10035 #endif /* USE_GTK */
10037 dpyinfo
->vertical_scroll_bar_cursor
10038 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
10040 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
10041 resource_name
, EMACS_CLASS
);
10042 #ifdef HAVE_XRMSETDATABASE
10043 XrmSetDatabase (dpyinfo
->display
, xrdb
);
10045 dpyinfo
->display
->db
= xrdb
;
10047 /* Put the rdb where we can find it in a way that works on
10049 dpyinfo
->xrdb
= xrdb
;
10051 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
10052 DefaultScreen (dpyinfo
->display
));
10053 select_visual (dpyinfo
);
10054 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
10055 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
10056 dpyinfo
->icon_bitmap_id
= -1;
10057 dpyinfo
->wm_type
= X_WMTYPE_UNKNOWN
;
10059 reset_mouse_highlight (&dpyinfo
->mouse_highlight
);
10061 /* See if we can construct pixel values from RGB values. */
10062 if (dpyinfo
->visual
->class == TrueColor
)
10064 get_bits_and_offset (dpyinfo
->visual
->red_mask
,
10065 &dpyinfo
->red_bits
, &dpyinfo
->red_offset
);
10066 get_bits_and_offset (dpyinfo
->visual
->blue_mask
,
10067 &dpyinfo
->blue_bits
, &dpyinfo
->blue_offset
);
10068 get_bits_and_offset (dpyinfo
->visual
->green_mask
,
10069 &dpyinfo
->green_bits
, &dpyinfo
->green_offset
);
10072 /* See if a private colormap is requested. */
10073 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
10075 if (dpyinfo
->visual
->class == PseudoColor
)
10078 value
= display_x_get_resource (dpyinfo
,
10079 build_string ("privateColormap"),
10080 build_string ("PrivateColormap"),
10082 if (STRINGP (value
)
10083 && (!strcmp (SSDATA (value
), "true")
10084 || !strcmp (SSDATA (value
), "on")))
10085 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
10089 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
10090 dpyinfo
->visual
, AllocNone
);
10094 /* If we are using Xft, the following precautions should be made:
10096 1. Make sure that the Xrender extension is added before the Xft one.
10097 Otherwise, the close-display hook set by Xft is called after the one
10098 for Xrender, and the former tries to re-add the latter. This results
10099 in inconsistency of internal states and leads to X protocol error when
10100 one reconnects to the same X server (Bug#1696).
10102 2. Check dpi value in X resources. It is better we use it as well,
10103 since Xft will use it, as will all Gnome applications. If our real DPI
10104 is smaller or larger than the one Xft uses, our font will look smaller
10105 or larger than other for other applications, even if it is the same
10106 font name (monospace-10 for example). */
10108 int event_base
, error_base
;
10112 XRenderQueryExtension (dpyinfo
->display
, &event_base
, &error_base
);
10114 v
= XGetDefault (dpyinfo
->display
, "Xft", "dpi");
10115 if (v
!= NULL
&& sscanf (v
, "%lf", &d
) == 1)
10116 dpyinfo
->resy
= dpyinfo
->resx
= d
;
10120 if (dpyinfo
->resy
< 1)
10122 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
10123 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
10124 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
10125 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10126 dpyinfo
->resy
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10127 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
10128 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
10129 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10130 dpyinfo
->resx
= (mm
< 1) ? 100 : pixels
* 25.4 / mm
;
10134 static const struct
10139 #define ATOM_REFS_INIT(string, member) \
10140 { string, offsetof (struct x_display_info, member) },
10141 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols
)
10142 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus
)
10143 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself
)
10144 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window
)
10145 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state
)
10146 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied
)
10147 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved
)
10148 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader
)
10149 ATOM_REFS_INIT ("Editres", Xatom_editres
)
10150 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD
)
10151 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP
)
10152 ATOM_REFS_INIT ("TEXT", Xatom_TEXT
)
10153 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT
)
10154 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING
)
10155 ATOM_REFS_INIT ("DELETE", Xatom_DELETE
)
10156 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE
)
10157 ATOM_REFS_INIT ("INCR", Xatom_INCR
)
10158 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP
)
10159 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS
)
10160 ATOM_REFS_INIT ("NULL", Xatom_NULL
)
10161 ATOM_REFS_INIT ("ATOM", Xatom_ATOM
)
10162 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR
)
10163 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER
)
10164 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO
)
10165 /* For properties of font. */
10166 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE
)
10167 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH
)
10168 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET
)
10169 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE
)
10170 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT
)
10171 /* Ghostscript support. */
10172 ATOM_REFS_INIT ("DONE", Xatom_DONE
)
10173 ATOM_REFS_INIT ("PAGE", Xatom_PAGE
)
10174 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar
)
10175 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED
)
10177 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state
)
10178 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen
)
10179 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
10180 Xatom_net_wm_state_maximized_horz
)
10181 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
10182 Xatom_net_wm_state_maximized_vert
)
10183 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky
)
10184 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden
)
10185 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type
)
10186 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
10187 Xatom_net_window_type_tooltip
)
10188 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name
)
10189 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name
)
10190 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported
)
10191 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check
)
10192 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity
)
10193 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window
)
10194 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents
)
10195 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop
)
10196 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea
)
10197 /* Session management */
10198 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID
)
10199 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop
)
10200 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr
)
10204 const int atom_count
= ARRAYELTS (atom_refs
);
10205 /* 1 for _XSETTINGS_SN */
10206 const int total_atom_count
= 1 + atom_count
;
10207 Atom
*atoms_return
= xmalloc (total_atom_count
* sizeof *atoms_return
);
10208 char **atom_names
= xmalloc (total_atom_count
* sizeof *atom_names
);
10209 static char const xsettings_fmt
[] = "_XSETTINGS_S%d";
10210 char xsettings_atom_name
[sizeof xsettings_fmt
- 2
10211 + INT_STRLEN_BOUND (int)];
10213 for (i
= 0; i
< atom_count
; i
++)
10214 atom_names
[i
] = (char *) atom_refs
[i
].name
;
10216 /* Build _XSETTINGS_SN atom name */
10217 sprintf (xsettings_atom_name
, xsettings_fmt
,
10218 XScreenNumberOfScreen (dpyinfo
->screen
));
10219 atom_names
[i
] = xsettings_atom_name
;
10221 XInternAtoms (dpyinfo
->display
, atom_names
, total_atom_count
,
10222 False
, atoms_return
);
10224 for (i
= 0; i
< atom_count
; i
++)
10225 *(Atom
*) ((char *) dpyinfo
+ atom_refs
[i
].offset
) = atoms_return
[i
];
10227 /* Manual copy of last atom */
10228 dpyinfo
->Xatom_xsettings_sel
= atoms_return
[i
];
10230 xfree (atom_names
);
10231 xfree (atoms_return
);
10234 dpyinfo
->x_dnd_atoms_size
= 8;
10235 dpyinfo
->x_dnd_atoms
= xmalloc (sizeof *dpyinfo
->x_dnd_atoms
10236 * dpyinfo
->x_dnd_atoms_size
);
10238 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
10239 gray_bits
, gray_width
, gray_height
,
10242 x_setup_pointer_blanking (dpyinfo
);
10245 xim_initialize (dpyinfo
, resource_name
);
10248 xsettings_initialize (dpyinfo
);
10250 connection
= ConnectionNumber (dpyinfo
->display
);
10252 /* This is only needed for distinguishing keyboard and process input. */
10253 if (connection
!= 0)
10254 add_keyboard_wait_descriptor (connection
);
10257 fcntl (connection
, F_SETOWN
, getpid ());
10258 #endif /* ! defined (F_SETOWN) */
10260 if (interrupt_input
)
10261 init_sigio (connection
);
10265 XFontStruct
*xfont
= NULL
;
10266 XrmValue d
, fr
, to
;
10269 dpy
= dpyinfo
->display
;
10270 d
.addr
= (XPointer
)&dpy
;
10271 d
.size
= sizeof (Display
*);
10272 fr
.addr
= XtDefaultFont
;
10273 fr
.size
= sizeof (XtDefaultFont
);
10274 to
.size
= sizeof (Font
*);
10275 to
.addr
= (XPointer
)&font
;
10276 x_catch_errors (dpy
);
10277 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
10279 if (x_had_errors_p (dpy
) || !((xfont
= XQueryFont (dpy
, font
))))
10280 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
10282 XFreeFont (dpy
, xfont
);
10283 x_uncatch_errors ();
10287 /* See if we should run in synchronous mode. This is useful
10288 for debugging X code. */
10291 value
= display_x_get_resource (dpyinfo
,
10292 build_string ("synchronous"),
10293 build_string ("Synchronous"),
10295 if (STRINGP (value
)
10296 && (!strcmp (SSDATA (value
), "true")
10297 || !strcmp (SSDATA (value
), "on")))
10298 XSynchronize (dpyinfo
->display
, True
);
10303 value
= display_x_get_resource (dpyinfo
,
10304 build_string ("useXIM"),
10305 build_string ("UseXIM"),
10308 if (STRINGP (value
)
10309 && (!strcmp (SSDATA (value
), "false")
10310 || !strcmp (SSDATA (value
), "off")))
10313 if (STRINGP (value
)
10314 && (!strcmp (SSDATA (value
), "true")
10315 || !strcmp (SSDATA (value
), "on")))
10321 /* Only do this for the very first display in the Emacs session.
10322 Ignore X session management when Emacs was first started on a
10324 if (terminal
->id
== 1)
10325 x_session_initialize (dpyinfo
);
10333 /* Get rid of display DPYINFO, deleting all frames on it,
10334 and without sending any more commands to the X server. */
10337 x_delete_display (struct x_display_info
*dpyinfo
)
10339 struct terminal
*t
;
10341 /* Close all frames and delete the generic struct terminal for this
10343 for (t
= terminal_list
; t
; t
= t
->next_terminal
)
10344 if (t
->type
== output_x_window
&& t
->display_info
.x
== dpyinfo
)
10347 /* Close X session management when we close its display. */
10348 if (t
->id
== 1 && x_session_have_connection ())
10349 x_session_close ();
10351 delete_terminal (t
);
10355 if (next_noop_dpyinfo
== dpyinfo
)
10356 next_noop_dpyinfo
= dpyinfo
->next
;
10358 if (x_display_list
== dpyinfo
)
10359 x_display_list
= dpyinfo
->next
;
10362 struct x_display_info
*tail
;
10364 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10365 if (tail
->next
== dpyinfo
)
10366 tail
->next
= tail
->next
->next
;
10369 xfree (dpyinfo
->x_id_name
);
10370 xfree (dpyinfo
->x_dnd_atoms
);
10371 xfree (dpyinfo
->color_cells
);
10375 #ifdef USE_X_TOOLKIT
10377 /* Atimer callback function for TIMER. Called every 0.1s to process
10378 Xt timeouts, if needed. We must avoid calling XtAppPending as
10379 much as possible because that function does an implicit XFlush
10380 that slows us down. */
10383 x_process_timeouts (struct atimer
*timer
)
10386 x_timeout_atimer_activated_flag
= 0;
10387 if (toolkit_scroll_bar_interaction
|| popup_activated ())
10389 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
10390 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
10391 /* Reactivate the atimer for next time. */
10392 x_activate_timeout_atimer ();
10397 /* Install an asynchronous timer that processes Xt timeout events
10398 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10399 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10400 function whenever these variables are set. This is necessary
10401 because some widget sets use timeouts internally, for example the
10402 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10403 processed, these widgets don't behave normally. */
10406 x_activate_timeout_atimer (void)
10409 if (!x_timeout_atimer_activated_flag
)
10411 struct timespec interval
= make_timespec (0, 100 * 1000 * 1000);
10412 start_atimer (ATIMER_RELATIVE
, interval
, x_process_timeouts
, 0);
10413 x_timeout_atimer_activated_flag
= 1;
10418 #endif /* USE_X_TOOLKIT */
10421 /* Set up use of X before we make the first connection. */
10423 static struct redisplay_interface x_redisplay_interface
=
10425 x_frame_parm_handlers
,
10429 x_clear_end_of_line
,
10431 x_after_update_window_line
,
10432 x_update_window_begin
,
10433 x_update_window_end
,
10435 x_clear_window_mouse_face
,
10436 x_get_glyph_overhangs
,
10437 x_fix_overlapping_area
,
10438 x_draw_fringe_bitmap
,
10439 0, /* define_fringe_bitmap */
10440 0, /* destroy_fringe_bitmap */
10441 x_compute_glyph_string_overhangs
,
10442 x_draw_glyph_string
,
10443 x_define_frame_cursor
,
10444 x_clear_frame_area
,
10445 x_draw_window_cursor
,
10446 x_draw_vertical_window_border
,
10447 x_draw_window_divider
,
10448 x_shift_glyphs_for_insert
10452 /* This function is called when the last frame on a display is deleted. */
10454 x_delete_terminal (struct terminal
*terminal
)
10456 struct x_display_info
*dpyinfo
= terminal
->display_info
.x
;
10457 int connection
= -1;
10459 /* Protect against recursive calls. delete_frame in
10460 delete_terminal calls us back when it deletes our last frame. */
10461 if (!terminal
->name
)
10466 /* We must close our connection to the XIM server before closing the
10469 xim_close_dpy (dpyinfo
);
10472 /* If called from x_connection_closed, the display may already be closed
10473 and dpyinfo->display was set to 0 to indicate that. */
10474 if (dpyinfo
->display
)
10476 connection
= ConnectionNumber (dpyinfo
->display
);
10478 x_destroy_all_bitmaps (dpyinfo
);
10479 XSetCloseDownMode (dpyinfo
->display
, DestroyAll
);
10481 /* Whether or not XCloseDisplay destroys the associated resource
10482 database depends on the version of libX11. To avoid both
10483 crash and memory leak, we dissociate the database from the
10484 display and then destroy dpyinfo->xrdb ourselves.
10486 Unfortunately, the above strategy does not work in some
10487 situations due to a bug in newer versions of libX11: because
10488 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
10489 dpy->db is NULL, XCloseDisplay destroys the associated
10490 database whereas it has not been created by XGetDefault
10491 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
10492 don't destroy the database here in order to avoid the crash
10493 in the above situations for now, though that may cause memory
10494 leaks in other situations. */
10496 #ifdef HAVE_XRMSETDATABASE
10497 XrmSetDatabase (dpyinfo
->display
, NULL
);
10499 dpyinfo
->display
->db
= NULL
;
10501 /* We used to call XrmDestroyDatabase from x_delete_display, but
10502 some older versions of libX11 crash if we call it after
10503 closing all the displays. */
10504 XrmDestroyDatabase (dpyinfo
->xrdb
);
10508 xg_display_close (dpyinfo
->display
);
10510 #ifdef USE_X_TOOLKIT
10511 XtCloseDisplay (dpyinfo
->display
);
10513 XCloseDisplay (dpyinfo
->display
);
10515 #endif /* ! USE_GTK */
10518 /* No more input on this descriptor. */
10519 if (connection
!= -1)
10520 delete_keyboard_wait_descriptor (connection
);
10522 /* Mark as dead. */
10523 dpyinfo
->display
= NULL
;
10524 x_delete_display (dpyinfo
);
10528 /* Create a struct terminal, initialize it with the X11 specific
10529 functions and make DISPLAY->TERMINAL point to it. */
10531 static struct terminal
*
10532 x_create_terminal (struct x_display_info
*dpyinfo
)
10534 struct terminal
*terminal
;
10536 terminal
= create_terminal (output_x_window
, &x_redisplay_interface
);
10538 terminal
->display_info
.x
= dpyinfo
;
10539 dpyinfo
->terminal
= terminal
;
10541 /* kboard is initialized in x_term_init. */
10543 terminal
->clear_frame_hook
= x_clear_frame
;
10544 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
10545 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
10546 terminal
->ring_bell_hook
= XTring_bell
;
10547 terminal
->toggle_invisible_pointer_hook
= XTtoggle_invisible_pointer
;
10548 terminal
->update_begin_hook
= x_update_begin
;
10549 terminal
->update_end_hook
= x_update_end
;
10550 terminal
->read_socket_hook
= XTread_socket
;
10551 terminal
->frame_up_to_date_hook
= XTframe_up_to_date
;
10552 terminal
->mouse_position_hook
= XTmouse_position
;
10553 terminal
->frame_rehighlight_hook
= XTframe_rehighlight
;
10554 terminal
->frame_raise_lower_hook
= XTframe_raise_lower
;
10555 terminal
->fullscreen_hook
= XTfullscreen_hook
;
10556 terminal
->menu_show_hook
= x_menu_show
;
10557 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
10558 terminal
->popup_dialog_hook
= xw_popup_dialog
;
10560 terminal
->set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10561 terminal
->condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10562 terminal
->redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10563 terminal
->judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10564 terminal
->delete_frame_hook
= x_destroy_window
;
10565 terminal
->delete_terminal_hook
= x_delete_terminal
;
10566 /* Other hooks are NULL by default. */
10572 x_initialize (void)
10577 any_help_event_p
= 0;
10578 ignore_next_mouse_click_timeout
= 0;
10581 current_count
= -1;
10584 /* Try to use interrupt input; if we can't, then start polling. */
10585 Fset_input_interrupt_mode (Qt
);
10587 #ifdef USE_X_TOOLKIT
10588 XtToolkitInitialize ();
10590 Xt_app_con
= XtCreateApplicationContext ();
10592 /* Register a converter from strings to pixels, which uses
10593 Emacs' color allocation infrastructure. */
10594 XtAppSetTypeConverter (Xt_app_con
,
10595 XtRString
, XtRPixel
, cvt_string_to_pixel
,
10596 cvt_string_to_pixel_args
,
10597 XtNumber (cvt_string_to_pixel_args
),
10598 XtCacheByDisplay
, cvt_pixel_dtor
);
10600 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
10603 #ifdef USE_TOOLKIT_SCROLL_BARS
10605 xaw3d_arrow_scroll
= False
;
10606 xaw3d_pick_top
= True
;
10610 /* Note that there is no real way portable across R3/R4 to get the
10611 original error handler. */
10612 XSetErrorHandler (x_error_handler
);
10613 XSetIOErrorHandler (x_io_error_quitter
);
10618 syms_of_xterm (void)
10620 x_error_message
= NULL
;
10622 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
10623 DEFSYM (Qlatin_1
, "latin-1");
10626 xg_default_icon_file
= build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
10627 staticpro (&xg_default_icon_file
);
10629 DEFSYM (Qx_gtk_map_stock
, "x-gtk-map-stock");
10632 DEFVAR_BOOL ("x-use-underline-position-properties",
10633 x_use_underline_position_properties
,
10634 doc
: /* Non-nil means make use of UNDERLINE_POSITION font properties.
10635 A value of nil means ignore them. If you encounter fonts with bogus
10636 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10637 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10638 to override the font's UNDERLINE_POSITION for small font display
10640 x_use_underline_position_properties
= 1;
10642 DEFVAR_BOOL ("x-underline-at-descent-line",
10643 x_underline_at_descent_line
,
10644 doc
: /* Non-nil means to draw the underline at the same place as the descent line.
10645 A value of nil means to draw the underline according to the value of the
10646 variable `x-use-underline-position-properties', which is usually at the
10647 baseline level. The default value is nil. */);
10648 x_underline_at_descent_line
= 0;
10650 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10651 x_mouse_click_focus_ignore_position
,
10652 doc
: /* Non-nil means that a mouse click to focus a frame does not move point.
10653 This variable is only used when the window manager requires that you
10654 click on a frame to select it (give it focus). In that case, a value
10655 of nil, means that the selected window and cursor position changes to
10656 reflect the mouse click position, while a non-nil value means that the
10657 selected window or cursor position is preserved. */);
10658 x_mouse_click_focus_ignore_position
= 0;
10660 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars
,
10661 doc
: /* Which toolkit scroll bars Emacs uses, if any.
10662 A value of nil means Emacs doesn't use toolkit scroll bars.
10663 With the X Window system, the value is a symbol describing the
10664 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
10665 With MS Windows or Nextstep, the value is t. */);
10666 #ifdef USE_TOOLKIT_SCROLL_BARS
10668 Vx_toolkit_scroll_bars
= intern_c_string ("motif");
10669 #elif defined HAVE_XAW3D
10670 Vx_toolkit_scroll_bars
= intern_c_string ("xaw3d");
10672 Vx_toolkit_scroll_bars
= intern_c_string ("gtk");
10674 Vx_toolkit_scroll_bars
= intern_c_string ("xaw");
10677 Vx_toolkit_scroll_bars
= Qnil
;
10680 DEFSYM (Qmodifier_value
, "modifier-value");
10681 DEFSYM (Qalt
, "alt");
10682 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10683 DEFSYM (Qhyper
, "hyper");
10684 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10685 DEFSYM (Qmeta
, "meta");
10686 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10687 DEFSYM (Qsuper
, "super");
10688 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10690 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym
,
10691 doc
: /* Which keys Emacs uses for the alt modifier.
10692 This should be one of the symbols `alt', `hyper', `meta', `super'.
10693 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10694 is nil, which is the same as `alt'. */);
10695 Vx_alt_keysym
= Qnil
;
10697 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym
,
10698 doc
: /* Which keys Emacs uses for the hyper modifier.
10699 This should be one of the symbols `alt', `hyper', `meta', `super'.
10700 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10701 default is nil, which is the same as `hyper'. */);
10702 Vx_hyper_keysym
= Qnil
;
10704 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym
,
10705 doc
: /* Which keys Emacs uses for the meta modifier.
10706 This should be one of the symbols `alt', `hyper', `meta', `super'.
10707 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10708 default is nil, which is the same as `meta'. */);
10709 Vx_meta_keysym
= Qnil
;
10711 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym
,
10712 doc
: /* Which keys Emacs uses for the super modifier.
10713 This should be one of the symbols `alt', `hyper', `meta', `super'.
10714 For example, `super' means use the Super_L and Super_R keysyms. The
10715 default is nil, which is the same as `super'. */);
10716 Vx_super_keysym
= Qnil
;
10718 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table
,
10719 doc
: /* Hash table of character codes indexed by X keysym codes. */);
10720 Vx_keysym_table
= make_hash_table (hashtest_eql
, make_number (900),
10721 make_float (DEFAULT_REHASH_SIZE
),
10722 make_float (DEFAULT_REHASH_THRESHOLD
),