* lisp.h (Mouse_HLInfo): Move from here...
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2
3 Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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/>. */
19
20 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
21 /* Xt features made by Fred Pierresteguy. */
22
23 #include <config.h>
24 #include <stdio.h>
25
26 #ifdef HAVE_X_WINDOWS
27
28 #include "lisp.h"
29 #include "blockinput.h"
30 #include "syssignal.h"
31
32 /* This may include sys/types.h, and that somehow loses
33 if this is not done before the other system files. */
34 #include "xterm.h"
35 #include <X11/cursorfont.h>
36
37 /* Load sys/types.h if not already loaded.
38 In some systems loading it twice is suicidal. */
39 #ifndef makedev
40 #include <sys/types.h>
41 #endif /* makedev */
42
43 #include <sys/ioctl.h>
44
45 #include "systime.h"
46
47 #include <fcntl.h>
48 #include <errno.h>
49 #include <sys/stat.h>
50 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
51 /* #include <sys/param.h> */
52
53 #include "charset.h"
54 #include "character.h"
55 #include "coding.h"
56 #include "frame.h"
57 #include "dispextern.h"
58 #include "fontset.h"
59 #include "termhooks.h"
60 #include "termopts.h"
61 #include "termchar.h"
62 #include "emacs-icon.h"
63 #include "disptab.h"
64 #include "buffer.h"
65 #include "window.h"
66 #include "keyboard.h"
67 #include "intervals.h"
68 #include "process.h"
69 #include "atimer.h"
70 #include "keymap.h"
71 #include "font.h"
72 #include "xsettings.h"
73 #include "xgselect.h"
74 #include "sysselect.h"
75
76 #ifdef USE_X_TOOLKIT
77 #include <X11/Shell.h>
78 #endif
79
80 #include <unistd.h>
81
82 #ifdef USE_GTK
83 #include "gtkutil.h"
84 #ifdef HAVE_GTK3
85 #include <X11/Xproto.h>
86 #endif
87 #endif
88
89 #ifdef USE_LUCID
90 #include "../lwlib/xlwmenu.h"
91 #endif
92
93 #ifdef USE_X_TOOLKIT
94 #if !defined (NO_EDITRES)
95 #define HACK_EDITRES
96 extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
97 #endif /* not NO_EDITRES */
98
99 /* Include toolkit specific headers for the scroll bar widget. */
100
101 #ifdef USE_TOOLKIT_SCROLL_BARS
102 #if defined USE_MOTIF
103 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
104 #include <Xm/ScrollBar.h>
105 #else /* !USE_MOTIF i.e. use Xaw */
106
107 #ifdef HAVE_XAW3D
108 #include <X11/Xaw3d/Simple.h>
109 #include <X11/Xaw3d/Scrollbar.h>
110 #include <X11/Xaw3d/ThreeD.h>
111 #else /* !HAVE_XAW3D */
112 #include <X11/Xaw/Simple.h>
113 #include <X11/Xaw/Scrollbar.h>
114 #endif /* !HAVE_XAW3D */
115 #ifndef XtNpickTop
116 #define XtNpickTop "pickTop"
117 #endif /* !XtNpickTop */
118 #endif /* !USE_MOTIF */
119 #endif /* USE_TOOLKIT_SCROLL_BARS */
120
121 #endif /* USE_X_TOOLKIT */
122
123 #ifdef USE_X_TOOLKIT
124 #include "widget.h"
125 #ifndef XtNinitialState
126 #define XtNinitialState "initialState"
127 #endif
128 #endif
129
130 #include "bitmaps/gray.xbm"
131
132 #ifdef HAVE_XKB
133 #include <X11/XKBlib.h>
134 #endif
135
136 /* Default to using XIM if available. */
137 #ifdef USE_XIM
138 int use_xim = 1;
139 #else
140 int use_xim = 0; /* configure --without-xim */
141 #endif
142
143 \f
144
145 /* Non-zero means that a HELP_EVENT has been generated since Emacs
146 start. */
147
148 static bool any_help_event_p;
149
150 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
151 static Lisp_Object last_window;
152
153 /* This is a chain of structures for all the X displays currently in
154 use. */
155
156 struct x_display_info *x_display_list;
157
158 /* This is a list of cons cells, each of the form (NAME
159 . FONT-LIST-CACHE), one for each element of x_display_list and in
160 the same order. NAME is the name of the frame. FONT-LIST-CACHE
161 records previous values returned by x-list-fonts. */
162
163 Lisp_Object x_display_name_list;
164
165 /* This is a frame waiting to be auto-raised, within XTread_socket. */
166
167 static struct frame *pending_autoraise_frame;
168
169 /* This is a frame waiting for an event matching mask, within XTread_socket. */
170
171 static struct {
172 struct frame *f;
173 int eventtype;
174 } pending_event_wait;
175
176 #ifdef USE_X_TOOLKIT
177 /* The application context for Xt use. */
178 XtAppContext Xt_app_con;
179 static String Xt_default_resources[] = {0};
180
181 /* Non-zero means user is interacting with a toolkit scroll bar. */
182
183 static int toolkit_scroll_bar_interaction;
184 #endif /* USE_X_TOOLKIT */
185
186 /* Non-zero timeout value means ignore next mouse click if it arrives
187 before that timeout elapses (i.e. as part of the same sequence of
188 events resulting from clicking on a frame to select it). */
189
190 static unsigned long ignore_next_mouse_click_timeout;
191
192 /* Mouse movement.
193
194 Formerly, we used PointerMotionHintMask (in standard_event_mask)
195 so that we would have to call XQueryPointer after each MotionNotify
196 event to ask for another such event. However, this made mouse tracking
197 slow, and there was a bug that made it eventually stop.
198
199 Simply asking for MotionNotify all the time seems to work better.
200
201 In order to avoid asking for motion events and then throwing most
202 of them away or busy-polling the server for mouse positions, we ask
203 the server for pointer motion hints. This means that we get only
204 one event per group of mouse movements. "Groups" are delimited by
205 other kinds of events (focus changes and button clicks, for
206 example), or by XQueryPointer calls; when one of these happens, we
207 get another MotionNotify event the next time the mouse moves. This
208 is at least as efficient as getting motion events when mouse
209 tracking is on, and I suspect only negligibly worse when tracking
210 is off. */
211
212 /* Where the mouse was last time we reported a mouse event. */
213
214 static XRectangle last_mouse_glyph;
215 static struct frame *last_mouse_glyph_frame;
216
217 /* The scroll bar in which the last X motion event occurred.
218
219 If the last X motion event occurred in a scroll bar, we set this so
220 XTmouse_position can know whether to report a scroll bar motion or
221 an ordinary motion.
222
223 If the last X motion event didn't occur in a scroll bar, we set
224 this to Qnil, to tell XTmouse_position to return an ordinary motion
225 event. */
226
227 static Lisp_Object last_mouse_scroll_bar;
228
229 /* This is a hack. We would really prefer that XTmouse_position would
230 return the time associated with the position it returns, but there
231 doesn't seem to be any way to wrest the time-stamp from the server
232 along with the position query. So, we just keep track of the time
233 of the last movement we received, and return that in hopes that
234 it's somewhat accurate. */
235
236 static Time last_mouse_movement_time;
237
238 /* Time for last user interaction as returned in X events. */
239
240 static Time last_user_time;
241
242 /* Incremented by XTread_socket whenever it really tries to read
243 events. */
244
245 static int volatile input_signal_count;
246
247 /* Used locally within XTread_socket. */
248
249 static int x_noop_count;
250
251 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
252
253 static Lisp_Object Qvendor_specific_keysyms;
254 static Lisp_Object Qlatin_1;
255
256 #ifdef USE_GTK
257 /* The name of the Emacs icon file. */
258 static Lisp_Object xg_default_icon_file;
259
260 /* Used in gtkutil.c. */
261 Lisp_Object Qx_gtk_map_stock;
262 #endif
263
264 /* Some functions take this as char *, not const char *. */
265 static char emacs_class[] = EMACS_CLASS;
266
267 enum xembed_info
268 {
269 XEMBED_MAPPED = 1 << 0
270 };
271
272 enum xembed_message
273 {
274 XEMBED_EMBEDDED_NOTIFY = 0,
275 XEMBED_WINDOW_ACTIVATE = 1,
276 XEMBED_WINDOW_DEACTIVATE = 2,
277 XEMBED_REQUEST_FOCUS = 3,
278 XEMBED_FOCUS_IN = 4,
279 XEMBED_FOCUS_OUT = 5,
280 XEMBED_FOCUS_NEXT = 6,
281 XEMBED_FOCUS_PREV = 7,
282
283 XEMBED_MODALITY_ON = 10,
284 XEMBED_MODALITY_OFF = 11,
285 XEMBED_REGISTER_ACCELERATOR = 12,
286 XEMBED_UNREGISTER_ACCELERATOR = 13,
287 XEMBED_ACTIVATE_ACCELERATOR = 14
288 };
289
290 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
291 static void x_set_window_size_1 (struct frame *, int, int, int);
292 static void x_raise_frame (struct frame *);
293 static void x_lower_frame (struct frame *);
294 static const XColor *x_color_cells (Display *, int *);
295 static int x_io_error_quitter (Display *);
296 static struct terminal *x_create_terminal (struct x_display_info *);
297 void x_delete_terminal (struct terminal *);
298 static void x_update_end (struct frame *);
299 static void XTframe_up_to_date (struct frame *);
300 static void XTset_terminal_modes (struct terminal *);
301 static void XTreset_terminal_modes (struct terminal *);
302 static void x_clear_frame (struct frame *);
303 static _Noreturn void x_ins_del_lines (struct frame *, int, int);
304 static void frame_highlight (struct frame *);
305 static void frame_unhighlight (struct frame *);
306 static void x_new_focus_frame (struct x_display_info *, struct frame *);
307 static void x_focus_changed (int, int, struct x_display_info *,
308 struct frame *, struct input_event *);
309 static void x_detect_focus_change (struct x_display_info *,
310 XEvent *, struct input_event *);
311 static void XTframe_rehighlight (struct frame *);
312 static void x_frame_rehighlight (struct x_display_info *);
313 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
314 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
315 enum text_cursor_kinds);
316
317 static void x_clip_to_row (struct window *, struct glyph_row *, int, GC);
318 static void x_flush (struct frame *f);
319 static void x_update_begin (struct frame *);
320 static void x_update_window_begin (struct window *);
321 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window);
322 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
323 enum scroll_bar_part *,
324 Lisp_Object *, Lisp_Object *,
325 Time *);
326 static int x_handle_net_wm_state (struct frame *, XPropertyEvent *);
327 static void x_check_fullscreen (struct frame *);
328 static void x_check_expected_move (struct frame *, int, int);
329 static void x_sync_with_move (struct frame *, int, int, int);
330 static int handle_one_xevent (struct x_display_info *, XEvent *,
331 int *, struct input_event *);
332 #ifdef USE_GTK
333 static int x_dispatch_event (XEvent *, Display *);
334 #endif
335 /* Don't declare this _Noreturn because we want no
336 interference with debugging failing X calls. */
337 static void x_connection_closed (Display *, const char *);
338 static void x_wm_set_window_state (struct frame *, int);
339 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
340 static void x_initialize (void);
341
342
343 /* Flush display of frame F, or of all frames if F is null. */
344
345 static void
346 x_flush (struct frame *f)
347 {
348 /* Don't call XFlush when it is not safe to redisplay; the X
349 connection may be broken. */
350 if (!NILP (Vinhibit_redisplay))
351 return;
352
353 block_input ();
354 if (f)
355 {
356 eassert (FRAME_X_P (f));
357 XFlush (FRAME_X_DISPLAY (f));
358 }
359 else
360 {
361 /* Flush all displays and so all frames on them. */
362 struct x_display_info *xdi;
363 for (xdi = x_display_list; xdi; xdi = xdi->next)
364 XFlush (xdi->display);
365 }
366 unblock_input ();
367 }
368
369
370 /* Remove calls to XFlush by defining XFlush to an empty replacement.
371 Calls to XFlush should be unnecessary because the X output buffer
372 is flushed automatically as needed by calls to XPending,
373 XNextEvent, or XWindowEvent according to the XFlush man page.
374 XTread_socket calls XPending. Removing XFlush improves
375 performance. */
376
377 #define XFlush(DISPLAY) (void) 0
378
379 \f
380 /***********************************************************************
381 Debugging
382 ***********************************************************************/
383
384 #if 0
385
386 /* This is a function useful for recording debugging information about
387 the sequence of occurrences in this file. */
388
389 struct record
390 {
391 char *locus;
392 int type;
393 };
394
395 struct record event_record[100];
396
397 int event_record_index;
398
399 void
400 record_event (char *locus, int type)
401 {
402 if (event_record_index == sizeof (event_record) / sizeof (struct record))
403 event_record_index = 0;
404
405 event_record[event_record_index].locus = locus;
406 event_record[event_record_index].type = type;
407 event_record_index++;
408 }
409
410 #endif /* 0 */
411
412
413 \f
414 /* Return the struct x_display_info corresponding to DPY. */
415
416 struct x_display_info *
417 x_display_info_for_display (Display *dpy)
418 {
419 struct x_display_info *dpyinfo;
420
421 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
422 if (dpyinfo->display == dpy)
423 return dpyinfo;
424
425 return 0;
426 }
427
428 static Window
429 x_find_topmost_parent (struct frame *f)
430 {
431 struct x_output *x = f->output_data.x;
432 Window win = None, wi = x->parent_desc;
433 Display *dpy = FRAME_X_DISPLAY (f);
434
435 while (wi != FRAME_X_DISPLAY_INFO (f)->root_window)
436 {
437 Window root;
438 Window *children;
439 unsigned int nchildren;
440
441 win = wi;
442 XQueryTree (dpy, win, &root, &wi, &children, &nchildren);
443 XFree (children);
444 }
445
446 return win;
447 }
448
449 #define OPAQUE 0xffffffff
450
451 void
452 x_set_frame_alpha (struct frame *f)
453 {
454 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
455 Display *dpy = FRAME_X_DISPLAY (f);
456 Window win = FRAME_OUTER_WINDOW (f);
457 double alpha = 1.0;
458 double alpha_min = 1.0;
459 unsigned long opac;
460 Window parent;
461
462 if (dpyinfo->x_highlight_frame == f)
463 alpha = f->alpha[0];
464 else
465 alpha = f->alpha[1];
466
467 if (FLOATP (Vframe_alpha_lower_limit))
468 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
469 else if (INTEGERP (Vframe_alpha_lower_limit))
470 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
471
472 if (alpha < 0.0)
473 return;
474 else if (alpha > 1.0)
475 alpha = 1.0;
476 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
477 alpha = alpha_min;
478
479 opac = alpha * OPAQUE;
480
481 x_catch_errors (dpy);
482
483 /* If there is a parent from the window manager, put the property there
484 also, to work around broken window managers that fail to do that.
485 Do this unconditionally as this function is called on reparent when
486 alpha has not changed on the frame. */
487
488 parent = x_find_topmost_parent (f);
489 if (parent != None)
490 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
491 XA_CARDINAL, 32, PropModeReplace,
492 (unsigned char *) &opac, 1L);
493
494 /* return unless necessary */
495 {
496 unsigned char *data;
497 Atom actual;
498 int rc, format;
499 unsigned long n, left;
500
501 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
502 0L, 1L, False, XA_CARDINAL,
503 &actual, &format, &n, &left,
504 &data);
505
506 if (rc == Success && actual != None)
507 {
508 unsigned long value = *(unsigned long *)data;
509 XFree (data);
510 if (value == opac)
511 {
512 x_uncatch_errors ();
513 return;
514 }
515 }
516 }
517
518 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
519 XA_CARDINAL, 32, PropModeReplace,
520 (unsigned char *) &opac, 1L);
521 x_uncatch_errors ();
522 }
523
524 int
525 x_display_pixel_height (struct x_display_info *dpyinfo)
526 {
527 return HeightOfScreen (dpyinfo->screen);
528 }
529
530 int
531 x_display_pixel_width (struct x_display_info *dpyinfo)
532 {
533 return WidthOfScreen (dpyinfo->screen);
534 }
535
536 \f
537 /***********************************************************************
538 Starting and ending an update
539 ***********************************************************************/
540
541 /* Start an update of frame F. This function is installed as a hook
542 for update_begin, i.e. it is called when update_begin is called.
543 This function is called prior to calls to x_update_window_begin for
544 each window being updated. Currently, there is nothing to do here
545 because all interesting stuff is done on a window basis. */
546
547 static void
548 x_update_begin (struct frame *f)
549 {
550 /* Nothing to do. */
551 }
552
553
554 /* Start update of window W. Set output_cursor to the cursor
555 position of W. */
556
557 static void
558 x_update_window_begin (struct window *w)
559 {
560 struct frame *f = XFRAME (WINDOW_FRAME (w));
561 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
562
563 set_output_cursor (&w->cursor);
564
565 block_input ();
566
567 if (f == hlinfo->mouse_face_mouse_frame)
568 {
569 /* Don't do highlighting for mouse motion during the update. */
570 hlinfo->mouse_face_defer = 1;
571
572 /* If F needs to be redrawn, simply forget about any prior mouse
573 highlighting. */
574 if (FRAME_GARBAGED_P (f))
575 hlinfo->mouse_face_window = Qnil;
576 }
577
578 unblock_input ();
579 }
580
581
582 /* Draw a vertical window border from (x,y0) to (x,y1) */
583
584 static void
585 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
586 {
587 struct frame *f = XFRAME (WINDOW_FRAME (w));
588 struct face *face;
589
590 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
591 if (face)
592 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
593 face->foreground);
594
595 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
596 f->output_data.x->normal_gc, x, y0, x, y1);
597 }
598
599 /* End update of window W.
600
601 Draw vertical borders between horizontally adjacent windows, and
602 display W's cursor if CURSOR_ON_P is non-zero.
603
604 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
605 glyphs in mouse-face were overwritten. In that case we have to
606 make sure that the mouse-highlight is properly redrawn.
607
608 W may be a menu bar pseudo-window in case we don't have X toolkit
609 support. Such windows don't have a cursor, so don't display it
610 here. */
611
612 static void
613 x_update_window_end (struct window *w, bool cursor_on_p,
614 bool mouse_face_overwritten_p)
615 {
616 if (!w->pseudo_window_p)
617 {
618 block_input ();
619
620 if (cursor_on_p)
621 display_and_set_cursor (w, 1, output_cursor.hpos,
622 output_cursor.vpos,
623 output_cursor.x, output_cursor.y);
624
625 if (draw_window_fringes (w, 1))
626 x_draw_vertical_border (w);
627
628 unblock_input ();
629 }
630
631 /* If a row with mouse-face was overwritten, arrange for
632 XTframe_up_to_date to redisplay the mouse highlight. */
633 if (mouse_face_overwritten_p)
634 reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
635 }
636
637
638 /* End update of frame F. This function is installed as a hook in
639 update_end. */
640
641 static void
642 x_update_end (struct frame *f)
643 {
644 /* Mouse highlight may be displayed again. */
645 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
646
647 #ifndef XFlush
648 block_input ();
649 XFlush (FRAME_X_DISPLAY (f));
650 unblock_input ();
651 #endif
652 }
653
654
655 /* This function is called from various places in xdisp.c
656 whenever a complete update has been performed. */
657
658 static void
659 XTframe_up_to_date (struct frame *f)
660 {
661 if (FRAME_X_P (f))
662 FRAME_MOUSE_UPDATE (f);
663 }
664
665
666 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
667 arrow bitmaps, or clear the fringes if no bitmaps are required
668 before DESIRED_ROW is made current. This function is called from
669 update_window_line only if it is known that there are differences
670 between bitmaps to be drawn between current row and DESIRED_ROW. */
671
672 static void
673 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
674 {
675 struct frame *f;
676 int width, height;
677
678 eassert (w);
679
680 if (!desired_row->mode_line_p && !w->pseudo_window_p)
681 desired_row->redraw_fringe_bitmaps_p = 1;
682
683 /* When a window has disappeared, make sure that no rest of
684 full-width rows stays visible in the internal border. Could
685 check here if updated window is the leftmost/rightmost window,
686 but I guess it's not worth doing since vertically split windows
687 are almost never used, internal border is rarely set, and the
688 overhead is very small. */
689 if (windows_or_buffers_changed
690 && desired_row->full_width_p
691 && (f = XFRAME (w->frame),
692 width = FRAME_INTERNAL_BORDER_WIDTH (f),
693 width != 0)
694 && (height = desired_row->visible_height,
695 height > 0))
696 {
697 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
698
699 block_input ();
700 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
701 0, y, width, height, False);
702 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
703 FRAME_PIXEL_WIDTH (f) - width,
704 y, width, height, False);
705 unblock_input ();
706 }
707 }
708
709 static void
710 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
711 {
712 struct frame *f = XFRAME (WINDOW_FRAME (w));
713 Display *display = FRAME_X_DISPLAY (f);
714 Window window = FRAME_X_WINDOW (f);
715 GC gc = f->output_data.x->normal_gc;
716 struct face *face = p->face;
717
718 /* Must clip because of partially visible lines. */
719 x_clip_to_row (w, row, -1, gc);
720
721 if (!p->overlay_p)
722 {
723 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
724
725 /* In case the same realized face is used for fringes and
726 for something displayed in the text (e.g. face `region' on
727 mono-displays, the fill style may have been changed to
728 FillSolid in x_draw_glyph_string_background. */
729 if (face->stipple)
730 XSetFillStyle (display, face->gc, FillOpaqueStippled);
731 else
732 XSetForeground (display, face->gc, face->background);
733
734 #ifdef USE_TOOLKIT_SCROLL_BARS
735 /* If the fringe is adjacent to the left (right) scroll bar of a
736 leftmost (rightmost, respectively) window, then extend its
737 background to the gap between the fringe and the bar. */
738 if ((WINDOW_LEFTMOST_P (w)
739 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
740 || (WINDOW_RIGHTMOST_P (w)
741 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
742 {
743 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
744
745 if (sb_width > 0)
746 {
747 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
748 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
749 * FRAME_COLUMN_WIDTH (f));
750
751 if (bx < 0)
752 {
753 /* Bitmap fills the fringe. */
754 if (bar_area_x + bar_area_width == p->x)
755 bx = bar_area_x + sb_width;
756 else if (p->x + p->wd == bar_area_x)
757 bx = bar_area_x;
758 if (bx >= 0)
759 {
760 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
761
762 nx = bar_area_width - sb_width;
763 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
764 row->y));
765 ny = row->visible_height;
766 }
767 }
768 else
769 {
770 if (bar_area_x + bar_area_width == bx)
771 {
772 bx = bar_area_x + sb_width;
773 nx += bar_area_width - sb_width;
774 }
775 else if (bx + nx == bar_area_x)
776 nx += bar_area_width - sb_width;
777 }
778 }
779 }
780 #endif
781 if (bx >= 0 && nx > 0)
782 XFillRectangle (display, window, face->gc, bx, by, nx, ny);
783
784 if (!face->stipple)
785 XSetForeground (display, face->gc, face->foreground);
786 }
787
788 if (p->which)
789 {
790 char *bits;
791 Pixmap pixmap, clipmask = (Pixmap) 0;
792 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
793 XGCValues gcv;
794
795 if (p->wd > 8)
796 bits = (char *) (p->bits + p->dh);
797 else
798 bits = (char *) p->bits + p->dh;
799
800 /* Draw the bitmap. I believe these small pixmaps can be cached
801 by the server. */
802 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
803 (p->cursor_p
804 ? (p->overlay_p ? face->background
805 : f->output_data.x->cursor_pixel)
806 : face->foreground),
807 face->background, depth);
808
809 if (p->overlay_p)
810 {
811 clipmask = XCreatePixmapFromBitmapData (display,
812 FRAME_X_DISPLAY_INFO (f)->root_window,
813 bits, p->wd, p->h,
814 1, 0, 1);
815 gcv.clip_mask = clipmask;
816 gcv.clip_x_origin = p->x;
817 gcv.clip_y_origin = p->y;
818 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
819 }
820
821 XCopyArea (display, pixmap, window, gc, 0, 0,
822 p->wd, p->h, p->x, p->y);
823 XFreePixmap (display, pixmap);
824
825 if (p->overlay_p)
826 {
827 gcv.clip_mask = (Pixmap) 0;
828 XChangeGC (display, gc, GCClipMask, &gcv);
829 XFreePixmap (display, clipmask);
830 }
831 }
832
833 XSetClipMask (display, gc, None);
834 }
835
836 \f
837
838 /* This is called when starting Emacs and when restarting after
839 suspend. When starting Emacs, no X window is mapped. And nothing
840 must be done to Emacs's own window if it is suspended (though that
841 rarely happens). */
842
843 static void
844 XTset_terminal_modes (struct terminal *terminal)
845 {
846 }
847
848 /* This is called when exiting or suspending Emacs. Exiting will make
849 the X-windows go away, and suspending requires no action. */
850
851 static void
852 XTreset_terminal_modes (struct terminal *terminal)
853 {
854 }
855
856 \f
857 /***********************************************************************
858 Glyph display
859 ***********************************************************************/
860
861
862
863 static void x_set_glyph_string_clipping (struct glyph_string *);
864 static void x_set_glyph_string_gc (struct glyph_string *);
865 static void x_draw_glyph_string_foreground (struct glyph_string *);
866 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
867 static void x_draw_glyph_string_box (struct glyph_string *);
868 static void x_draw_glyph_string (struct glyph_string *);
869 static _Noreturn void x_delete_glyphs (struct frame *, int);
870 static void x_compute_glyph_string_overhangs (struct glyph_string *);
871 static void x_set_cursor_gc (struct glyph_string *);
872 static void x_set_mode_line_face_gc (struct glyph_string *);
873 static void x_set_mouse_face_gc (struct glyph_string *);
874 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
875 unsigned long *, double, int);
876 static void x_setup_relief_color (struct frame *, struct relief *,
877 double, int, unsigned long);
878 static void x_setup_relief_colors (struct glyph_string *);
879 static void x_draw_image_glyph_string (struct glyph_string *);
880 static void x_draw_image_relief (struct glyph_string *);
881 static void x_draw_image_foreground (struct glyph_string *);
882 static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
883 static void x_clear_glyph_string_rect (struct glyph_string *, int,
884 int, int, int);
885 static void x_draw_relief_rect (struct frame *, int, int, int, int,
886 int, int, int, int, int, int,
887 XRectangle *);
888 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
889 int, int, int, XRectangle *);
890 static void x_scroll_bar_clear (struct frame *);
891
892 #ifdef GLYPH_DEBUG
893 static void x_check_font (struct frame *, struct font *);
894 #endif
895
896
897 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
898 face. */
899
900 static void
901 x_set_cursor_gc (struct glyph_string *s)
902 {
903 if (s->font == FRAME_FONT (s->f)
904 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
905 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
906 && !s->cmp)
907 s->gc = s->f->output_data.x->cursor_gc;
908 else
909 {
910 /* Cursor on non-default face: must merge. */
911 XGCValues xgcv;
912 unsigned long mask;
913
914 xgcv.background = s->f->output_data.x->cursor_pixel;
915 xgcv.foreground = s->face->background;
916
917 /* If the glyph would be invisible, try a different foreground. */
918 if (xgcv.foreground == xgcv.background)
919 xgcv.foreground = s->face->foreground;
920 if (xgcv.foreground == xgcv.background)
921 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
922 if (xgcv.foreground == xgcv.background)
923 xgcv.foreground = s->face->foreground;
924
925 /* Make sure the cursor is distinct from text in this face. */
926 if (xgcv.background == s->face->background
927 && xgcv.foreground == s->face->foreground)
928 {
929 xgcv.background = s->face->foreground;
930 xgcv.foreground = s->face->background;
931 }
932
933 IF_DEBUG (x_check_font (s->f, s->font));
934 xgcv.graphics_exposures = False;
935 mask = GCForeground | GCBackground | GCGraphicsExposures;
936
937 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
938 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
939 mask, &xgcv);
940 else
941 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
942 = XCreateGC (s->display, s->window, mask, &xgcv);
943
944 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
945 }
946 }
947
948
949 /* Set up S->gc of glyph string S for drawing text in mouse face. */
950
951 static void
952 x_set_mouse_face_gc (struct glyph_string *s)
953 {
954 int face_id;
955 struct face *face;
956
957 /* What face has to be used last for the mouse face? */
958 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
959 face = FACE_FROM_ID (s->f, face_id);
960 if (face == NULL)
961 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
962
963 if (s->first_glyph->type == CHAR_GLYPH)
964 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
965 else
966 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
967 s->face = FACE_FROM_ID (s->f, face_id);
968 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
969
970 if (s->font == s->face->font)
971 s->gc = s->face->gc;
972 else
973 {
974 /* Otherwise construct scratch_cursor_gc with values from FACE
975 except for FONT. */
976 XGCValues xgcv;
977 unsigned long mask;
978
979 xgcv.background = s->face->background;
980 xgcv.foreground = s->face->foreground;
981 xgcv.graphics_exposures = False;
982 mask = GCForeground | GCBackground | GCGraphicsExposures;
983
984 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
985 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
986 mask, &xgcv);
987 else
988 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
989 = XCreateGC (s->display, s->window, mask, &xgcv);
990
991 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
992
993 }
994 eassert (s->gc != 0);
995 }
996
997
998 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
999 Faces to use in the mode line have already been computed when the
1000 matrix was built, so there isn't much to do, here. */
1001
1002 static void
1003 x_set_mode_line_face_gc (struct glyph_string *s)
1004 {
1005 s->gc = s->face->gc;
1006 }
1007
1008
1009 /* Set S->gc of glyph string S for drawing that glyph string. Set
1010 S->stippled_p to a non-zero value if the face of S has a stipple
1011 pattern. */
1012
1013 static void
1014 x_set_glyph_string_gc (struct glyph_string *s)
1015 {
1016 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1017
1018 if (s->hl == DRAW_NORMAL_TEXT)
1019 {
1020 s->gc = s->face->gc;
1021 s->stippled_p = s->face->stipple != 0;
1022 }
1023 else if (s->hl == DRAW_INVERSE_VIDEO)
1024 {
1025 x_set_mode_line_face_gc (s);
1026 s->stippled_p = s->face->stipple != 0;
1027 }
1028 else if (s->hl == DRAW_CURSOR)
1029 {
1030 x_set_cursor_gc (s);
1031 s->stippled_p = 0;
1032 }
1033 else if (s->hl == DRAW_MOUSE_FACE)
1034 {
1035 x_set_mouse_face_gc (s);
1036 s->stippled_p = s->face->stipple != 0;
1037 }
1038 else if (s->hl == DRAW_IMAGE_RAISED
1039 || s->hl == DRAW_IMAGE_SUNKEN)
1040 {
1041 s->gc = s->face->gc;
1042 s->stippled_p = s->face->stipple != 0;
1043 }
1044 else
1045 {
1046 s->gc = s->face->gc;
1047 s->stippled_p = s->face->stipple != 0;
1048 }
1049
1050 /* GC must have been set. */
1051 eassert (s->gc != 0);
1052 }
1053
1054
1055 /* Set clipping for output of glyph string S. S may be part of a mode
1056 line or menu if we don't have X toolkit support. */
1057
1058 static void
1059 x_set_glyph_string_clipping (struct glyph_string *s)
1060 {
1061 XRectangle *r = s->clip;
1062 int n = get_glyph_string_clip_rects (s, r, 2);
1063
1064 if (n > 0)
1065 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
1066 s->num_clips = n;
1067 }
1068
1069
1070 /* Set SRC's clipping for output of glyph string DST. This is called
1071 when we are drawing DST's left_overhang or right_overhang only in
1072 the area of SRC. */
1073
1074 static void
1075 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1076 {
1077 XRectangle r;
1078
1079 r.x = src->x;
1080 r.width = src->width;
1081 r.y = src->y;
1082 r.height = src->height;
1083 dst->clip[0] = r;
1084 dst->num_clips = 1;
1085 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
1086 }
1087
1088
1089 /* RIF:
1090 Compute left and right overhang of glyph string S. */
1091
1092 static void
1093 x_compute_glyph_string_overhangs (struct glyph_string *s)
1094 {
1095 if (s->cmp == NULL
1096 && (s->first_glyph->type == CHAR_GLYPH
1097 || s->first_glyph->type == COMPOSITE_GLYPH))
1098 {
1099 struct font_metrics metrics;
1100
1101 if (s->first_glyph->type == CHAR_GLYPH)
1102 {
1103 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1104 struct font *font = s->font;
1105 int i;
1106
1107 for (i = 0; i < s->nchars; i++)
1108 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1109 font->driver->text_extents (font, code, s->nchars, &metrics);
1110 }
1111 else
1112 {
1113 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1114
1115 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1116 }
1117 s->right_overhang = (metrics.rbearing > metrics.width
1118 ? metrics.rbearing - metrics.width : 0);
1119 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1120 }
1121 else if (s->cmp)
1122 {
1123 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1124 s->left_overhang = - s->cmp->lbearing;
1125 }
1126 }
1127
1128
1129 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1130
1131 static void
1132 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1133 {
1134 XGCValues xgcv;
1135 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1136 XSetForeground (s->display, s->gc, xgcv.background);
1137 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
1138 XSetForeground (s->display, s->gc, xgcv.foreground);
1139 }
1140
1141
1142 /* Draw the background of glyph_string S. If S->background_filled_p
1143 is non-zero don't draw it. FORCE_P non-zero means draw the
1144 background even if it wouldn't be drawn normally. This is used
1145 when a string preceding S draws into the background of S, or S
1146 contains the first component of a composition. */
1147
1148 static void
1149 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1150 {
1151 /* Nothing to do if background has already been drawn or if it
1152 shouldn't be drawn in the first place. */
1153 if (!s->background_filled_p)
1154 {
1155 int box_line_width = max (s->face->box_line_width, 0);
1156
1157 if (s->stippled_p)
1158 {
1159 /* Fill background with a stipple pattern. */
1160 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1161 XFillRectangle (s->display, s->window, s->gc, s->x,
1162 s->y + box_line_width,
1163 s->background_width,
1164 s->height - 2 * box_line_width);
1165 XSetFillStyle (s->display, s->gc, FillSolid);
1166 s->background_filled_p = 1;
1167 }
1168 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1169 || s->font_not_found_p
1170 || s->extends_to_end_of_line_p
1171 || force_p)
1172 {
1173 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1174 s->background_width,
1175 s->height - 2 * box_line_width);
1176 s->background_filled_p = 1;
1177 }
1178 }
1179 }
1180
1181
1182 /* Draw the foreground of glyph string S. */
1183
1184 static void
1185 x_draw_glyph_string_foreground (struct glyph_string *s)
1186 {
1187 int i, x;
1188
1189 /* If first glyph of S has a left box line, start drawing the text
1190 of S to the right of that box line. */
1191 if (s->face->box != FACE_NO_BOX
1192 && s->first_glyph->left_box_line_p)
1193 x = s->x + eabs (s->face->box_line_width);
1194 else
1195 x = s->x;
1196
1197 /* Draw characters of S as rectangles if S's font could not be
1198 loaded. */
1199 if (s->font_not_found_p)
1200 {
1201 for (i = 0; i < s->nchars; ++i)
1202 {
1203 struct glyph *g = s->first_glyph + i;
1204 XDrawRectangle (s->display, s->window,
1205 s->gc, x, s->y, g->pixel_width - 1,
1206 s->height - 1);
1207 x += g->pixel_width;
1208 }
1209 }
1210 else
1211 {
1212 struct font *font = s->font;
1213 int boff = font->baseline_offset;
1214 int y;
1215
1216 if (font->vertical_centering)
1217 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1218
1219 y = s->ybase - boff;
1220 if (s->for_overlaps
1221 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1222 font->driver->draw (s, 0, s->nchars, x, y, 0);
1223 else
1224 font->driver->draw (s, 0, s->nchars, x, y, 1);
1225 if (s->face->overstrike)
1226 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1227 }
1228 }
1229
1230 /* Draw the foreground of composite glyph string S. */
1231
1232 static void
1233 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1234 {
1235 int i, j, x;
1236 struct font *font = s->font;
1237
1238 /* If first glyph of S has a left box line, start drawing the text
1239 of S to the right of that box line. */
1240 if (s->face && s->face->box != FACE_NO_BOX
1241 && s->first_glyph->left_box_line_p)
1242 x = s->x + eabs (s->face->box_line_width);
1243 else
1244 x = s->x;
1245
1246 /* S is a glyph string for a composition. S->cmp_from is the index
1247 of the first character drawn for glyphs of this composition.
1248 S->cmp_from == 0 means we are drawing the very first character of
1249 this composition. */
1250
1251 /* Draw a rectangle for the composition if the font for the very
1252 first character of the composition could not be loaded. */
1253 if (s->font_not_found_p)
1254 {
1255 if (s->cmp_from == 0)
1256 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
1257 s->width - 1, s->height - 1);
1258 }
1259 else if (! s->first_glyph->u.cmp.automatic)
1260 {
1261 int y = s->ybase;
1262
1263 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1264 /* TAB in a composition means display glyphs with padding
1265 space on the left or right. */
1266 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1267 {
1268 int xx = x + s->cmp->offsets[j * 2];
1269 int yy = y - s->cmp->offsets[j * 2 + 1];
1270
1271 font->driver->draw (s, j, j + 1, xx, yy, 0);
1272 if (s->face->overstrike)
1273 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1274 }
1275 }
1276 else
1277 {
1278 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1279 Lisp_Object glyph;
1280 int y = s->ybase;
1281 int width = 0;
1282
1283 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1284 {
1285 glyph = LGSTRING_GLYPH (gstring, i);
1286 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1287 width += LGLYPH_WIDTH (glyph);
1288 else
1289 {
1290 int xoff, yoff, wadjust;
1291
1292 if (j < i)
1293 {
1294 font->driver->draw (s, j, i, x, y, 0);
1295 if (s->face->overstrike)
1296 font->driver->draw (s, j, i, x + 1, y, 0);
1297 x += width;
1298 }
1299 xoff = LGLYPH_XOFF (glyph);
1300 yoff = LGLYPH_YOFF (glyph);
1301 wadjust = LGLYPH_WADJUST (glyph);
1302 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1303 if (s->face->overstrike)
1304 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
1305 x += wadjust;
1306 j = i + 1;
1307 width = 0;
1308 }
1309 }
1310 if (j < i)
1311 {
1312 font->driver->draw (s, j, i, x, y, 0);
1313 if (s->face->overstrike)
1314 font->driver->draw (s, j, i, x + 1, y, 0);
1315 }
1316 }
1317 }
1318
1319
1320 /* Draw the foreground of glyph string S for glyphless characters. */
1321
1322 static void
1323 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1324 {
1325 struct glyph *glyph = s->first_glyph;
1326 XChar2b char2b[8];
1327 int x, i, j;
1328
1329 /* If first glyph of S has a left box line, start drawing the text
1330 of S to the right of that box line. */
1331 if (s->face && s->face->box != FACE_NO_BOX
1332 && s->first_glyph->left_box_line_p)
1333 x = s->x + eabs (s->face->box_line_width);
1334 else
1335 x = s->x;
1336
1337 s->char2b = char2b;
1338
1339 for (i = 0; i < s->nchars; i++, glyph++)
1340 {
1341 char buf[7], *str = NULL;
1342 int len = glyph->u.glyphless.len;
1343
1344 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1345 {
1346 if (len > 0
1347 && CHAR_TABLE_P (Vglyphless_char_display)
1348 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1349 >= 1))
1350 {
1351 Lisp_Object acronym
1352 = (! glyph->u.glyphless.for_no_font
1353 ? CHAR_TABLE_REF (Vglyphless_char_display,
1354 glyph->u.glyphless.ch)
1355 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1356 if (STRINGP (acronym))
1357 str = SSDATA (acronym);
1358 }
1359 }
1360 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1361 {
1362 sprintf (buf, "%0*X",
1363 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1364 glyph->u.glyphless.ch);
1365 str = buf;
1366 }
1367
1368 if (str)
1369 {
1370 int upper_len = (len + 1) / 2;
1371 unsigned code;
1372
1373 /* It is assured that all LEN characters in STR is ASCII. */
1374 for (j = 0; j < len; j++)
1375 {
1376 code = s->font->driver->encode_char (s->font, str[j]);
1377 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1378 }
1379 s->font->driver->draw (s, 0, upper_len,
1380 x + glyph->slice.glyphless.upper_xoff,
1381 s->ybase + glyph->slice.glyphless.upper_yoff,
1382 0);
1383 s->font->driver->draw (s, upper_len, len,
1384 x + glyph->slice.glyphless.lower_xoff,
1385 s->ybase + glyph->slice.glyphless.lower_yoff,
1386 0);
1387 }
1388 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1389 XDrawRectangle (s->display, s->window, s->gc,
1390 x, s->ybase - glyph->ascent,
1391 glyph->pixel_width - 1,
1392 glyph->ascent + glyph->descent - 1);
1393 x += glyph->pixel_width;
1394 }
1395 }
1396
1397 #ifdef USE_X_TOOLKIT
1398
1399 #ifdef USE_LUCID
1400
1401 /* Return the frame on which widget WIDGET is used.. Abort if frame
1402 cannot be determined. */
1403
1404 static struct frame *
1405 x_frame_of_widget (Widget widget)
1406 {
1407 struct x_display_info *dpyinfo;
1408 Lisp_Object tail, frame;
1409 struct frame *f;
1410
1411 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1412
1413 /* Find the top-level shell of the widget. Note that this function
1414 can be called when the widget is not yet realized, so XtWindow
1415 (widget) == 0. That's the reason we can't simply use
1416 x_any_window_to_frame. */
1417 while (!XtIsTopLevelShell (widget))
1418 widget = XtParent (widget);
1419
1420 /* Look for a frame with that top-level widget. Allocate the color
1421 on that frame to get the right gamma correction value. */
1422 FOR_EACH_FRAME (tail, frame)
1423 {
1424 f = XFRAME (frame);
1425 if (FRAME_X_P (f)
1426 && f->output_data.nothing != 1
1427 && FRAME_X_DISPLAY_INFO (f) == dpyinfo
1428 && f->output_data.x->widget == widget)
1429 return f;
1430 }
1431 emacs_abort ();
1432 }
1433
1434 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1435 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1436 If this produces the same color as PIXEL, try a color where all RGB
1437 values have DELTA added. Return the allocated color in *PIXEL.
1438 DISPLAY is the X display, CMAP is the colormap to operate on.
1439 Value is true if successful. */
1440
1441 bool
1442 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
1443 unsigned long *pixel, double factor, int delta)
1444 {
1445 struct frame *f = x_frame_of_widget (widget);
1446 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
1447 }
1448
1449 #endif /* USE_LUCID */
1450
1451
1452 /* Structure specifying which arguments should be passed by Xt to
1453 cvt_string_to_pixel. We want the widget's screen and colormap. */
1454
1455 static XtConvertArgRec cvt_string_to_pixel_args[] =
1456 {
1457 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
1458 sizeof (Screen *)},
1459 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
1460 sizeof (Colormap)}
1461 };
1462
1463
1464 /* The address of this variable is returned by
1465 cvt_string_to_pixel. */
1466
1467 static Pixel cvt_string_to_pixel_value;
1468
1469
1470 /* Convert a color name to a pixel color.
1471
1472 DPY is the display we are working on.
1473
1474 ARGS is an array of *NARGS XrmValue structures holding additional
1475 information about the widget for which the conversion takes place.
1476 The contents of this array are determined by the specification
1477 in cvt_string_to_pixel_args.
1478
1479 FROM is a pointer to an XrmValue which points to the color name to
1480 convert. TO is an XrmValue in which to return the pixel color.
1481
1482 CLOSURE_RET is a pointer to user-data, in which we record if
1483 we allocated the color or not.
1484
1485 Value is True if successful, False otherwise. */
1486
1487 static Boolean
1488 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
1489 XrmValue *from, XrmValue *to,
1490 XtPointer *closure_ret)
1491 {
1492 Screen *screen;
1493 Colormap cmap;
1494 Pixel pixel;
1495 String color_name;
1496 XColor color;
1497
1498 if (*nargs != 2)
1499 {
1500 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1501 "wrongParameters", "cvt_string_to_pixel",
1502 "XtToolkitError",
1503 "Screen and colormap args required", NULL, NULL);
1504 return False;
1505 }
1506
1507 screen = *(Screen **) args[0].addr;
1508 cmap = *(Colormap *) args[1].addr;
1509 color_name = (String) from->addr;
1510
1511 if (strcmp (color_name, XtDefaultBackground) == 0)
1512 {
1513 *closure_ret = (XtPointer) False;
1514 pixel = WhitePixelOfScreen (screen);
1515 }
1516 else if (strcmp (color_name, XtDefaultForeground) == 0)
1517 {
1518 *closure_ret = (XtPointer) False;
1519 pixel = BlackPixelOfScreen (screen);
1520 }
1521 else if (XParseColor (dpy, cmap, color_name, &color)
1522 && x_alloc_nearest_color_1 (dpy, cmap, &color))
1523 {
1524 pixel = color.pixel;
1525 *closure_ret = (XtPointer) True;
1526 }
1527 else
1528 {
1529 String params[1];
1530 Cardinal nparams = 1;
1531
1532 params[0] = color_name;
1533 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1534 "badValue", "cvt_string_to_pixel",
1535 "XtToolkitError", "Invalid color `%s'",
1536 params, &nparams);
1537 return False;
1538 }
1539
1540 if (to->addr != NULL)
1541 {
1542 if (to->size < sizeof (Pixel))
1543 {
1544 to->size = sizeof (Pixel);
1545 return False;
1546 }
1547
1548 *(Pixel *) to->addr = pixel;
1549 }
1550 else
1551 {
1552 cvt_string_to_pixel_value = pixel;
1553 to->addr = (XtPointer) &cvt_string_to_pixel_value;
1554 }
1555
1556 to->size = sizeof (Pixel);
1557 return True;
1558 }
1559
1560
1561 /* Free a pixel color which was previously allocated via
1562 cvt_string_to_pixel. This is registered as the destructor
1563 for this type of resource via XtSetTypeConverter.
1564
1565 APP is the application context in which we work.
1566
1567 TO is a pointer to an XrmValue holding the color to free.
1568 CLOSURE is the value we stored in CLOSURE_RET for this color
1569 in cvt_string_to_pixel.
1570
1571 ARGS and NARGS are like for cvt_string_to_pixel. */
1572
1573 static void
1574 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
1575 Cardinal *nargs)
1576 {
1577 if (*nargs != 2)
1578 {
1579 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
1580 "XtToolkitError",
1581 "Screen and colormap arguments required",
1582 NULL, NULL);
1583 }
1584 else if (closure != NULL)
1585 {
1586 /* We did allocate the pixel, so free it. */
1587 Screen *screen = *(Screen **) args[0].addr;
1588 Colormap cmap = *(Colormap *) args[1].addr;
1589 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
1590 (Pixel *) to->addr, 1);
1591 }
1592 }
1593
1594
1595 #endif /* USE_X_TOOLKIT */
1596
1597
1598 /* Value is an array of XColor structures for the contents of the
1599 color map of display DPY. Set *NCELLS to the size of the array.
1600 Note that this probably shouldn't be called for large color maps,
1601 say a 24-bit TrueColor map. */
1602
1603 static const XColor *
1604 x_color_cells (Display *dpy, int *ncells)
1605 {
1606 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1607
1608 if (dpyinfo->color_cells == NULL)
1609 {
1610 Screen *screen = dpyinfo->screen;
1611 int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1612 int i;
1613
1614 dpyinfo->color_cells = xnmalloc (ncolor_cells,
1615 sizeof *dpyinfo->color_cells);
1616 dpyinfo->ncolor_cells = ncolor_cells;
1617
1618 for (i = 0; i < ncolor_cells; ++i)
1619 dpyinfo->color_cells[i].pixel = i;
1620
1621 XQueryColors (dpy, dpyinfo->cmap,
1622 dpyinfo->color_cells, ncolor_cells);
1623 }
1624
1625 *ncells = dpyinfo->ncolor_cells;
1626 return dpyinfo->color_cells;
1627 }
1628
1629
1630 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1631 colors in COLORS. Use cached information, if available. */
1632
1633 void
1634 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1635 {
1636 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1637
1638 if (dpyinfo->color_cells)
1639 {
1640 int i;
1641 for (i = 0; i < ncolors; ++i)
1642 {
1643 unsigned long pixel = colors[i].pixel;
1644 eassert (pixel < dpyinfo->ncolor_cells);
1645 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
1646 colors[i] = dpyinfo->color_cells[pixel];
1647 }
1648 }
1649 else
1650 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
1651 }
1652
1653
1654 /* On frame F, translate pixel color to RGB values for the color in
1655 COLOR. Use cached information, if available. */
1656
1657 void
1658 x_query_color (struct frame *f, XColor *color)
1659 {
1660 x_query_colors (f, color, 1);
1661 }
1662
1663
1664 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1665 exact match can't be allocated, try the nearest color available.
1666 Value is true if successful. Set *COLOR to the color
1667 allocated. */
1668
1669 static bool
1670 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
1671 {
1672 bool rc;
1673
1674 rc = XAllocColor (dpy, cmap, color) != 0;
1675 if (rc == 0)
1676 {
1677 /* If we got to this point, the colormap is full, so we're going
1678 to try to get the next closest color. The algorithm used is
1679 a least-squares matching, which is what X uses for closest
1680 color matching with StaticColor visuals. */
1681 int nearest, i;
1682 int max_color_delta = 255;
1683 int max_delta = 3 * max_color_delta;
1684 int nearest_delta = max_delta + 1;
1685 int ncells;
1686 const XColor *cells = x_color_cells (dpy, &ncells);
1687
1688 for (nearest = i = 0; i < ncells; ++i)
1689 {
1690 int dred = (color->red >> 8) - (cells[i].red >> 8);
1691 int dgreen = (color->green >> 8) - (cells[i].green >> 8);
1692 int dblue = (color->blue >> 8) - (cells[i].blue >> 8);
1693 int delta = dred * dred + dgreen * dgreen + dblue * dblue;
1694
1695 if (delta < nearest_delta)
1696 {
1697 nearest = i;
1698 nearest_delta = delta;
1699 }
1700 }
1701
1702 color->red = cells[nearest].red;
1703 color->green = cells[nearest].green;
1704 color->blue = cells[nearest].blue;
1705 rc = XAllocColor (dpy, cmap, color) != 0;
1706 }
1707 else
1708 {
1709 /* If allocation succeeded, and the allocated pixel color is not
1710 equal to a cached pixel color recorded earlier, there was a
1711 change in the colormap, so clear the color cache. */
1712 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1713 XColor *cached_color;
1714
1715 if (dpyinfo->color_cells
1716 && (cached_color = &dpyinfo->color_cells[color->pixel],
1717 (cached_color->red != color->red
1718 || cached_color->blue != color->blue
1719 || cached_color->green != color->green)))
1720 {
1721 xfree (dpyinfo->color_cells);
1722 dpyinfo->color_cells = NULL;
1723 dpyinfo->ncolor_cells = 0;
1724 }
1725 }
1726
1727 #ifdef DEBUG_X_COLORS
1728 if (rc)
1729 register_color (color->pixel);
1730 #endif /* DEBUG_X_COLORS */
1731
1732 return rc;
1733 }
1734
1735
1736 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1737 exact match can't be allocated, try the nearest color available.
1738 Value is true if successful. Set *COLOR to the color
1739 allocated. */
1740
1741 bool
1742 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
1743 {
1744 gamma_correct (f, color);
1745 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
1746 }
1747
1748
1749 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1750 It's necessary to do this instead of just using PIXEL directly to
1751 get color reference counts right. */
1752
1753 unsigned long
1754 x_copy_color (struct frame *f, long unsigned int pixel)
1755 {
1756 XColor color;
1757
1758 color.pixel = pixel;
1759 block_input ();
1760 x_query_color (f, &color);
1761 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
1762 unblock_input ();
1763 #ifdef DEBUG_X_COLORS
1764 register_color (pixel);
1765 #endif
1766 return color.pixel;
1767 }
1768
1769
1770 /* Brightness beyond which a color won't have its highlight brightness
1771 boosted.
1772
1773 Nominally, highlight colors for `3d' faces are calculated by
1774 brightening an object's color by a constant scale factor, but this
1775 doesn't yield good results for dark colors, so for colors who's
1776 brightness is less than this value (on a scale of 0-65535) have an
1777 use an additional additive factor.
1778
1779 The value here is set so that the default menu-bar/mode-line color
1780 (grey75) will not have its highlights changed at all. */
1781 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1782
1783
1784 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1785 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1786 If this produces the same color as PIXEL, try a color where all RGB
1787 values have DELTA added. Return the allocated color in *PIXEL.
1788 DISPLAY is the X display, CMAP is the colormap to operate on.
1789 Value is non-zero if successful. */
1790
1791 static bool
1792 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
1793 {
1794 XColor color, new;
1795 long bright;
1796 bool success_p;
1797
1798 /* Get RGB color values. */
1799 color.pixel = *pixel;
1800 x_query_color (f, &color);
1801
1802 /* Change RGB values by specified FACTOR. Avoid overflow! */
1803 eassert (factor >= 0);
1804 new.red = min (0xffff, factor * color.red);
1805 new.green = min (0xffff, factor * color.green);
1806 new.blue = min (0xffff, factor * color.blue);
1807
1808 /* Calculate brightness of COLOR. */
1809 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1810
1811 /* We only boost colors that are darker than
1812 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1813 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1814 /* Make an additive adjustment to NEW, because it's dark enough so
1815 that scaling by FACTOR alone isn't enough. */
1816 {
1817 /* How far below the limit this color is (0 - 1, 1 being darker). */
1818 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1819 /* The additive adjustment. */
1820 int min_delta = delta * dimness * factor / 2;
1821
1822 if (factor < 1)
1823 {
1824 new.red = max (0, new.red - min_delta);
1825 new.green = max (0, new.green - min_delta);
1826 new.blue = max (0, new.blue - min_delta);
1827 }
1828 else
1829 {
1830 new.red = min (0xffff, min_delta + new.red);
1831 new.green = min (0xffff, min_delta + new.green);
1832 new.blue = min (0xffff, min_delta + new.blue);
1833 }
1834 }
1835
1836 /* Try to allocate the color. */
1837 success_p = x_alloc_nearest_color (f, cmap, &new);
1838 if (success_p)
1839 {
1840 if (new.pixel == *pixel)
1841 {
1842 /* If we end up with the same color as before, try adding
1843 delta to the RGB values. */
1844 x_free_colors (f, &new.pixel, 1);
1845
1846 new.red = min (0xffff, delta + color.red);
1847 new.green = min (0xffff, delta + color.green);
1848 new.blue = min (0xffff, delta + color.blue);
1849 success_p = x_alloc_nearest_color (f, cmap, &new);
1850 }
1851 else
1852 success_p = 1;
1853 *pixel = new.pixel;
1854 }
1855
1856 return success_p;
1857 }
1858
1859
1860 /* Set up the foreground color for drawing relief lines of glyph
1861 string S. RELIEF is a pointer to a struct relief containing the GC
1862 with which lines will be drawn. Use a color that is FACTOR or
1863 DELTA lighter or darker than the relief's background which is found
1864 in S->f->output_data.x->relief_background. If such a color cannot
1865 be allocated, use DEFAULT_PIXEL, instead. */
1866
1867 static void
1868 x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
1869 {
1870 XGCValues xgcv;
1871 struct x_output *di = f->output_data.x;
1872 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
1873 unsigned long pixel;
1874 unsigned long background = di->relief_background;
1875 Colormap cmap = FRAME_X_COLORMAP (f);
1876 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1877 Display *dpy = FRAME_X_DISPLAY (f);
1878
1879 xgcv.graphics_exposures = False;
1880 xgcv.line_width = 1;
1881
1882 /* Free previously allocated color. The color cell will be reused
1883 when it has been freed as many times as it was allocated, so this
1884 doesn't affect faces using the same colors. */
1885 if (relief->gc
1886 && relief->allocated_p)
1887 {
1888 x_free_colors (f, &relief->pixel, 1);
1889 relief->allocated_p = 0;
1890 }
1891
1892 /* Allocate new color. */
1893 xgcv.foreground = default_pixel;
1894 pixel = background;
1895 if (dpyinfo->n_planes != 1
1896 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
1897 {
1898 relief->allocated_p = 1;
1899 xgcv.foreground = relief->pixel = pixel;
1900 }
1901
1902 if (relief->gc == 0)
1903 {
1904 xgcv.stipple = dpyinfo->gray;
1905 mask |= GCStipple;
1906 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
1907 }
1908 else
1909 XChangeGC (dpy, relief->gc, mask, &xgcv);
1910 }
1911
1912
1913 /* Set up colors for the relief lines around glyph string S. */
1914
1915 static void
1916 x_setup_relief_colors (struct glyph_string *s)
1917 {
1918 struct x_output *di = s->f->output_data.x;
1919 unsigned long color;
1920
1921 if (s->face->use_box_color_for_shadows_p)
1922 color = s->face->box_color;
1923 else if (s->first_glyph->type == IMAGE_GLYPH
1924 && s->img->pixmap
1925 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1926 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1927 else
1928 {
1929 XGCValues xgcv;
1930
1931 /* Get the background color of the face. */
1932 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
1933 color = xgcv.background;
1934 }
1935
1936 if (di->white_relief.gc == 0
1937 || color != di->relief_background)
1938 {
1939 di->relief_background = color;
1940 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1941 WHITE_PIX_DEFAULT (s->f));
1942 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1943 BLACK_PIX_DEFAULT (s->f));
1944 }
1945 }
1946
1947
1948 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1949 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1950 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1951 relief. LEFT_P non-zero means draw a relief on the left side of
1952 the rectangle. RIGHT_P non-zero means draw a relief on the right
1953 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1954 when drawing. */
1955
1956 static void
1957 x_draw_relief_rect (struct frame *f,
1958 int left_x, int top_y, int right_x, int bottom_y, int width,
1959 int raised_p, int top_p, int bot_p, int left_p, int right_p,
1960 XRectangle *clip_rect)
1961 {
1962 Display *dpy = FRAME_X_DISPLAY (f);
1963 Window window = FRAME_X_WINDOW (f);
1964 int i;
1965 GC gc;
1966
1967 if (raised_p)
1968 gc = f->output_data.x->white_relief.gc;
1969 else
1970 gc = f->output_data.x->black_relief.gc;
1971 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
1972
1973 /* This code is more complicated than it has to be, because of two
1974 minor hacks to make the boxes look nicer: (i) if width > 1, draw
1975 the outermost line using the black relief. (ii) Omit the four
1976 corner pixels. */
1977
1978 /* Top. */
1979 if (top_p)
1980 {
1981 if (width == 1)
1982 XDrawLine (dpy, window, gc,
1983 left_x + (left_p ? 1 : 0), top_y,
1984 right_x + (right_p ? 0 : 1), top_y);
1985
1986 for (i = 1; i < width; ++i)
1987 XDrawLine (dpy, window, gc,
1988 left_x + i * left_p, top_y + i,
1989 right_x + 1 - i * right_p, top_y + i);
1990 }
1991
1992 /* Left. */
1993 if (left_p)
1994 {
1995 if (width == 1)
1996 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
1997
1998 XClearArea (dpy, window, left_x, top_y, 1, 1, False);
1999 XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
2000
2001 for (i = (width > 1 ? 1 : 0); i < width; ++i)
2002 XDrawLine (dpy, window, gc,
2003 left_x + i, top_y + (i + 1) * top_p,
2004 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
2005 }
2006
2007 XSetClipMask (dpy, gc, None);
2008 if (raised_p)
2009 gc = f->output_data.x->black_relief.gc;
2010 else
2011 gc = f->output_data.x->white_relief.gc;
2012 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2013
2014 if (width > 1)
2015 {
2016 /* Outermost top line. */
2017 if (top_p)
2018 XDrawLine (dpy, window, gc,
2019 left_x + (left_p ? 1 : 0), top_y,
2020 right_x + (right_p ? 0 : 1), top_y);
2021
2022 /* Outermost left line. */
2023 if (left_p)
2024 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
2025 }
2026
2027 /* Bottom. */
2028 if (bot_p)
2029 {
2030 XDrawLine (dpy, window, gc,
2031 left_x + (left_p ? 1 : 0), bottom_y,
2032 right_x + (right_p ? 0 : 1), bottom_y);
2033 for (i = 1; i < width; ++i)
2034 XDrawLine (dpy, window, gc,
2035 left_x + i * left_p, bottom_y - i,
2036 right_x + 1 - i * right_p, bottom_y - i);
2037 }
2038
2039 /* Right. */
2040 if (right_p)
2041 {
2042 XClearArea (dpy, window, right_x, top_y, 1, 1, False);
2043 XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
2044 for (i = 0; i < width; ++i)
2045 XDrawLine (dpy, window, gc,
2046 right_x - i, top_y + (i + 1) * top_p,
2047 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
2048 }
2049
2050 XSetClipMask (dpy, gc, None);
2051 }
2052
2053
2054 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2055 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2056 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2057 left side of the rectangle. RIGHT_P non-zero means draw a line
2058 on the right side of the rectangle. CLIP_RECT is the clipping
2059 rectangle to use when drawing. */
2060
2061 static void
2062 x_draw_box_rect (struct glyph_string *s,
2063 int left_x, int top_y, int right_x, int bottom_y, int width,
2064 int left_p, int right_p, XRectangle *clip_rect)
2065 {
2066 XGCValues xgcv;
2067
2068 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2069 XSetForeground (s->display, s->gc, s->face->box_color);
2070 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2071
2072 /* Top. */
2073 XFillRectangle (s->display, s->window, s->gc,
2074 left_x, top_y, right_x - left_x + 1, width);
2075
2076 /* Left. */
2077 if (left_p)
2078 XFillRectangle (s->display, s->window, s->gc,
2079 left_x, top_y, width, bottom_y - top_y + 1);
2080
2081 /* Bottom. */
2082 XFillRectangle (s->display, s->window, s->gc,
2083 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2084
2085 /* Right. */
2086 if (right_p)
2087 XFillRectangle (s->display, s->window, s->gc,
2088 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2089
2090 XSetForeground (s->display, s->gc, xgcv.foreground);
2091 XSetClipMask (s->display, s->gc, None);
2092 }
2093
2094
2095 /* Draw a box around glyph string S. */
2096
2097 static void
2098 x_draw_glyph_string_box (struct glyph_string *s)
2099 {
2100 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2101 int left_p, right_p;
2102 struct glyph *last_glyph;
2103 XRectangle clip_rect;
2104
2105 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2106 ? WINDOW_RIGHT_EDGE_X (s->w)
2107 : window_box_right (s->w, s->area));
2108
2109 /* The glyph that may have a right box line. */
2110 last_glyph = (s->cmp || s->img
2111 ? s->first_glyph
2112 : s->first_glyph + s->nchars - 1);
2113
2114 width = eabs (s->face->box_line_width);
2115 raised_p = s->face->box == FACE_RAISED_BOX;
2116 left_x = s->x;
2117 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2118 ? last_x - 1
2119 : min (last_x, s->x + s->background_width) - 1);
2120 top_y = s->y;
2121 bottom_y = top_y + s->height - 1;
2122
2123 left_p = (s->first_glyph->left_box_line_p
2124 || (s->hl == DRAW_MOUSE_FACE
2125 && (s->prev == NULL
2126 || s->prev->hl != s->hl)));
2127 right_p = (last_glyph->right_box_line_p
2128 || (s->hl == DRAW_MOUSE_FACE
2129 && (s->next == NULL
2130 || s->next->hl != s->hl)));
2131
2132 get_glyph_string_clip_rect (s, &clip_rect);
2133
2134 if (s->face->box == FACE_SIMPLE_BOX)
2135 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2136 left_p, right_p, &clip_rect);
2137 else
2138 {
2139 x_setup_relief_colors (s);
2140 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2141 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2142 }
2143 }
2144
2145
2146 /* Draw foreground of image glyph string S. */
2147
2148 static void
2149 x_draw_image_foreground (struct glyph_string *s)
2150 {
2151 int x = s->x;
2152 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2153
2154 /* If first glyph of S has a left box line, start drawing it to the
2155 right of that line. */
2156 if (s->face->box != FACE_NO_BOX
2157 && s->first_glyph->left_box_line_p
2158 && s->slice.x == 0)
2159 x += eabs (s->face->box_line_width);
2160
2161 /* If there is a margin around the image, adjust x- and y-position
2162 by that margin. */
2163 if (s->slice.x == 0)
2164 x += s->img->hmargin;
2165 if (s->slice.y == 0)
2166 y += s->img->vmargin;
2167
2168 if (s->img->pixmap)
2169 {
2170 if (s->img->mask)
2171 {
2172 /* We can't set both a clip mask and use XSetClipRectangles
2173 because the latter also sets a clip mask. We also can't
2174 trust on the shape extension to be available
2175 (XShapeCombineRegion). So, compute the rectangle to draw
2176 manually. */
2177 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2178 | GCFunction);
2179 XGCValues xgcv;
2180 XRectangle clip_rect, image_rect, r;
2181
2182 xgcv.clip_mask = s->img->mask;
2183 xgcv.clip_x_origin = x;
2184 xgcv.clip_y_origin = y;
2185 xgcv.function = GXcopy;
2186 XChangeGC (s->display, s->gc, mask, &xgcv);
2187
2188 get_glyph_string_clip_rect (s, &clip_rect);
2189 image_rect.x = x;
2190 image_rect.y = y;
2191 image_rect.width = s->slice.width;
2192 image_rect.height = s->slice.height;
2193 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2194 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2195 s->slice.x + r.x - x, s->slice.y + r.y - y,
2196 r.width, r.height, r.x, r.y);
2197 }
2198 else
2199 {
2200 XRectangle clip_rect, image_rect, r;
2201
2202 get_glyph_string_clip_rect (s, &clip_rect);
2203 image_rect.x = x;
2204 image_rect.y = y;
2205 image_rect.width = s->slice.width;
2206 image_rect.height = s->slice.height;
2207 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2208 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2209 s->slice.x + r.x - x, s->slice.y + r.y - y,
2210 r.width, r.height, r.x, r.y);
2211
2212 /* When the image has a mask, we can expect that at
2213 least part of a mouse highlight or a block cursor will
2214 be visible. If the image doesn't have a mask, make
2215 a block cursor visible by drawing a rectangle around
2216 the image. I believe it's looking better if we do
2217 nothing here for mouse-face. */
2218 if (s->hl == DRAW_CURSOR)
2219 {
2220 int relief = eabs (s->img->relief);
2221 XDrawRectangle (s->display, s->window, s->gc,
2222 x - relief, y - relief,
2223 s->slice.width + relief*2 - 1,
2224 s->slice.height + relief*2 - 1);
2225 }
2226 }
2227 }
2228 else
2229 /* Draw a rectangle if image could not be loaded. */
2230 XDrawRectangle (s->display, s->window, s->gc, x, y,
2231 s->slice.width - 1, s->slice.height - 1);
2232 }
2233
2234
2235 /* Draw a relief around the image glyph string S. */
2236
2237 static void
2238 x_draw_image_relief (struct glyph_string *s)
2239 {
2240 int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
2241 XRectangle r;
2242 int x = s->x;
2243 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2244
2245 /* If first glyph of S has a left box line, start drawing it to the
2246 right of that line. */
2247 if (s->face->box != FACE_NO_BOX
2248 && s->first_glyph->left_box_line_p
2249 && s->slice.x == 0)
2250 x += eabs (s->face->box_line_width);
2251
2252 /* If there is a margin around the image, adjust x- and y-position
2253 by that margin. */
2254 if (s->slice.x == 0)
2255 x += s->img->hmargin;
2256 if (s->slice.y == 0)
2257 y += s->img->vmargin;
2258
2259 if (s->hl == DRAW_IMAGE_SUNKEN
2260 || s->hl == DRAW_IMAGE_RAISED)
2261 {
2262 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2263 raised_p = s->hl == DRAW_IMAGE_RAISED;
2264 }
2265 else
2266 {
2267 thick = eabs (s->img->relief);
2268 raised_p = s->img->relief > 0;
2269 }
2270
2271 x1 = x + s->slice.width - 1;
2272 y1 = y + s->slice.height - 1;
2273 top_p = bot_p = left_p = right_p = 0;
2274
2275 if (s->slice.x == 0)
2276 x -= thick, left_p = 1;
2277 if (s->slice.y == 0)
2278 y -= thick, top_p = 1;
2279 if (s->slice.x + s->slice.width == s->img->width)
2280 x1 += thick, right_p = 1;
2281 if (s->slice.y + s->slice.height == s->img->height)
2282 y1 += thick, bot_p = 1;
2283
2284 x_setup_relief_colors (s);
2285 get_glyph_string_clip_rect (s, &r);
2286 x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
2287 top_p, bot_p, left_p, right_p, &r);
2288 }
2289
2290
2291 /* Draw the foreground of image glyph string S to PIXMAP. */
2292
2293 static void
2294 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2295 {
2296 int x = 0;
2297 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2298
2299 /* If first glyph of S has a left box line, start drawing it to the
2300 right of that line. */
2301 if (s->face->box != FACE_NO_BOX
2302 && s->first_glyph->left_box_line_p
2303 && s->slice.x == 0)
2304 x += eabs (s->face->box_line_width);
2305
2306 /* If there is a margin around the image, adjust x- and y-position
2307 by that margin. */
2308 if (s->slice.x == 0)
2309 x += s->img->hmargin;
2310 if (s->slice.y == 0)
2311 y += s->img->vmargin;
2312
2313 if (s->img->pixmap)
2314 {
2315 if (s->img->mask)
2316 {
2317 /* We can't set both a clip mask and use XSetClipRectangles
2318 because the latter also sets a clip mask. We also can't
2319 trust on the shape extension to be available
2320 (XShapeCombineRegion). So, compute the rectangle to draw
2321 manually. */
2322 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2323 | GCFunction);
2324 XGCValues xgcv;
2325
2326 xgcv.clip_mask = s->img->mask;
2327 xgcv.clip_x_origin = x - s->slice.x;
2328 xgcv.clip_y_origin = y - s->slice.y;
2329 xgcv.function = GXcopy;
2330 XChangeGC (s->display, s->gc, mask, &xgcv);
2331
2332 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2333 s->slice.x, s->slice.y,
2334 s->slice.width, s->slice.height, x, y);
2335 XSetClipMask (s->display, s->gc, None);
2336 }
2337 else
2338 {
2339 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2340 s->slice.x, s->slice.y,
2341 s->slice.width, s->slice.height, x, y);
2342
2343 /* When the image has a mask, we can expect that at
2344 least part of a mouse highlight or a block cursor will
2345 be visible. If the image doesn't have a mask, make
2346 a block cursor visible by drawing a rectangle around
2347 the image. I believe it's looking better if we do
2348 nothing here for mouse-face. */
2349 if (s->hl == DRAW_CURSOR)
2350 {
2351 int r = eabs (s->img->relief);
2352 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2353 s->slice.width + r*2 - 1,
2354 s->slice.height + r*2 - 1);
2355 }
2356 }
2357 }
2358 else
2359 /* Draw a rectangle if image could not be loaded. */
2360 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2361 s->slice.width - 1, s->slice.height - 1);
2362 }
2363
2364
2365 /* Draw part of the background of glyph string S. X, Y, W, and H
2366 give the rectangle to draw. */
2367
2368 static void
2369 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2370 {
2371 if (s->stippled_p)
2372 {
2373 /* Fill background with a stipple pattern. */
2374 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2375 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2376 XSetFillStyle (s->display, s->gc, FillSolid);
2377 }
2378 else
2379 x_clear_glyph_string_rect (s, x, y, w, h);
2380 }
2381
2382
2383 /* Draw image glyph string S.
2384
2385 s->y
2386 s->x +-------------------------
2387 | s->face->box
2388 |
2389 | +-------------------------
2390 | | s->img->margin
2391 | |
2392 | | +-------------------
2393 | | | the image
2394
2395 */
2396
2397 static void
2398 x_draw_image_glyph_string (struct glyph_string *s)
2399 {
2400 int box_line_hwidth = eabs (s->face->box_line_width);
2401 int box_line_vwidth = max (s->face->box_line_width, 0);
2402 int height;
2403 Pixmap pixmap = None;
2404
2405 height = s->height;
2406 if (s->slice.y == 0)
2407 height -= box_line_vwidth;
2408 if (s->slice.y + s->slice.height >= s->img->height)
2409 height -= box_line_vwidth;
2410
2411 /* Fill background with face under the image. Do it only if row is
2412 taller than image or if image has a clip mask to reduce
2413 flickering. */
2414 s->stippled_p = s->face->stipple != 0;
2415 if (height > s->slice.height
2416 || s->img->hmargin
2417 || s->img->vmargin
2418 || s->img->mask
2419 || s->img->pixmap == 0
2420 || s->width != s->background_width)
2421 {
2422 if (s->img->mask)
2423 {
2424 /* Create a pixmap as large as the glyph string. Fill it
2425 with the background color. Copy the image to it, using
2426 its mask. Copy the temporary pixmap to the display. */
2427 Screen *screen = FRAME_X_SCREEN (s->f);
2428 int depth = DefaultDepthOfScreen (screen);
2429
2430 /* Create a pixmap as large as the glyph string. */
2431 pixmap = XCreatePixmap (s->display, s->window,
2432 s->background_width,
2433 s->height, depth);
2434
2435 /* Don't clip in the following because we're working on the
2436 pixmap. */
2437 XSetClipMask (s->display, s->gc, None);
2438
2439 /* Fill the pixmap with the background color/stipple. */
2440 if (s->stippled_p)
2441 {
2442 /* Fill background with a stipple pattern. */
2443 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2444 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
2445 XFillRectangle (s->display, pixmap, s->gc,
2446 0, 0, s->background_width, s->height);
2447 XSetFillStyle (s->display, s->gc, FillSolid);
2448 XSetTSOrigin (s->display, s->gc, 0, 0);
2449 }
2450 else
2451 {
2452 XGCValues xgcv;
2453 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2454 &xgcv);
2455 XSetForeground (s->display, s->gc, xgcv.background);
2456 XFillRectangle (s->display, pixmap, s->gc,
2457 0, 0, s->background_width, s->height);
2458 XSetForeground (s->display, s->gc, xgcv.foreground);
2459 }
2460 }
2461 else
2462 {
2463 int x = s->x;
2464 int y = s->y;
2465
2466 if (s->first_glyph->left_box_line_p
2467 && s->slice.x == 0)
2468 x += box_line_hwidth;
2469
2470 if (s->slice.y == 0)
2471 y += box_line_vwidth;
2472
2473 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2474 }
2475
2476 s->background_filled_p = 1;
2477 }
2478
2479 /* Draw the foreground. */
2480 if (pixmap != None)
2481 {
2482 x_draw_image_foreground_1 (s, pixmap);
2483 x_set_glyph_string_clipping (s);
2484 XCopyArea (s->display, pixmap, s->window, s->gc,
2485 0, 0, s->background_width, s->height, s->x, s->y);
2486 XFreePixmap (s->display, pixmap);
2487 }
2488 else
2489 x_draw_image_foreground (s);
2490
2491 /* If we must draw a relief around the image, do it. */
2492 if (s->img->relief
2493 || s->hl == DRAW_IMAGE_RAISED
2494 || s->hl == DRAW_IMAGE_SUNKEN)
2495 x_draw_image_relief (s);
2496 }
2497
2498
2499 /* Draw stretch glyph string S. */
2500
2501 static void
2502 x_draw_stretch_glyph_string (struct glyph_string *s)
2503 {
2504 eassert (s->first_glyph->type == STRETCH_GLYPH);
2505
2506 if (s->hl == DRAW_CURSOR
2507 && !x_stretch_cursor_p)
2508 {
2509 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2510 wide as the stretch glyph. */
2511 int width, background_width = s->background_width;
2512 int x = s->x;
2513
2514 if (!s->row->reversed_p)
2515 {
2516 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2517
2518 if (x < left_x)
2519 {
2520 background_width -= left_x - x;
2521 x = left_x;
2522 }
2523 }
2524 else
2525 {
2526 /* In R2L rows, draw the cursor on the right edge of the
2527 stretch glyph. */
2528 int right_x = window_box_right_offset (s->w, TEXT_AREA);
2529
2530 if (x + background_width > right_x)
2531 background_width -= x - right_x;
2532 x += background_width;
2533 }
2534 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2535 if (s->row->reversed_p)
2536 x -= width;
2537
2538 /* Draw cursor. */
2539 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2540
2541 /* Clear rest using the GC of the original non-cursor face. */
2542 if (width < background_width)
2543 {
2544 int y = s->y;
2545 int w = background_width - width, h = s->height;
2546 XRectangle r;
2547 GC gc;
2548
2549 if (!s->row->reversed_p)
2550 x += width;
2551 else
2552 x = s->x;
2553 if (s->row->mouse_face_p
2554 && cursor_in_mouse_face_p (s->w))
2555 {
2556 x_set_mouse_face_gc (s);
2557 gc = s->gc;
2558 }
2559 else
2560 gc = s->face->gc;
2561
2562 get_glyph_string_clip_rect (s, &r);
2563 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2564
2565 if (s->face->stipple)
2566 {
2567 /* Fill background with a stipple pattern. */
2568 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2569 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2570 XSetFillStyle (s->display, gc, FillSolid);
2571 }
2572 else
2573 {
2574 XGCValues xgcv;
2575 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2576 XSetForeground (s->display, gc, xgcv.background);
2577 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2578 XSetForeground (s->display, gc, xgcv.foreground);
2579 }
2580 }
2581 }
2582 else if (!s->background_filled_p)
2583 {
2584 int background_width = s->background_width;
2585 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2586
2587 /* Don't draw into left margin, fringe or scrollbar area
2588 except for header line and mode line. */
2589 if (x < left_x && !s->row->mode_line_p)
2590 {
2591 background_width -= left_x - x;
2592 x = left_x;
2593 }
2594 if (background_width > 0)
2595 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2596 }
2597
2598 s->background_filled_p = 1;
2599 }
2600
2601 /*
2602 Draw a wavy line under S. The wave fills wave_height pixels from y0.
2603
2604 x0 wave_length = 2
2605 --
2606 y0 * * * * *
2607 |* * * * * * * * *
2608 wave_height = 3 | * * * *
2609
2610 */
2611
2612 static void
2613 x_draw_underwave (struct glyph_string *s)
2614 {
2615 int wave_height = 3, wave_length = 2;
2616 int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
2617 XRectangle wave_clip, string_clip, final_clip;
2618
2619 dx = wave_length;
2620 dy = wave_height - 1;
2621 x0 = s->x;
2622 y0 = s->ybase - wave_height + 3;
2623 width = s->width;
2624 xmax = x0 + width;
2625
2626 /* Find and set clipping rectangle */
2627
2628 wave_clip.x = x0;
2629 wave_clip.y = y0;
2630 wave_clip.width = width;
2631 wave_clip.height = wave_height;
2632 get_glyph_string_clip_rect (s, &string_clip);
2633
2634 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
2635 return;
2636
2637 XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
2638
2639 /* Draw the waves */
2640
2641 x1 = x0 - (x0 % dx);
2642 x2 = x1 + dx;
2643 odd = (x1/dx) % 2;
2644 y1 = y2 = y0;
2645
2646 if (odd)
2647 y1 += dy;
2648 else
2649 y2 += dy;
2650
2651 if (INT_MAX - dx < xmax)
2652 emacs_abort ();
2653
2654 while (x1 <= xmax)
2655 {
2656 XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
2657 x1 = x2, y1 = y2;
2658 x2 += dx, y2 = y0 + odd*dy;
2659 odd = !odd;
2660 }
2661
2662 /* Restore previous clipping rectangle(s) */
2663 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
2664 }
2665
2666
2667 /* Draw glyph string S. */
2668
2669 static void
2670 x_draw_glyph_string (struct glyph_string *s)
2671 {
2672 bool relief_drawn_p = 0;
2673
2674 /* If S draws into the background of its successors, draw the
2675 background of the successors first so that S can draw into it.
2676 This makes S->next use XDrawString instead of XDrawImageString. */
2677 if (s->next && s->right_overhang && !s->for_overlaps)
2678 {
2679 int width;
2680 struct glyph_string *next;
2681
2682 for (width = 0, next = s->next;
2683 next && width < s->right_overhang;
2684 width += next->width, next = next->next)
2685 if (next->first_glyph->type != IMAGE_GLYPH)
2686 {
2687 x_set_glyph_string_gc (next);
2688 x_set_glyph_string_clipping (next);
2689 if (next->first_glyph->type == STRETCH_GLYPH)
2690 x_draw_stretch_glyph_string (next);
2691 else
2692 x_draw_glyph_string_background (next, 1);
2693 next->num_clips = 0;
2694 }
2695 }
2696
2697 /* Set up S->gc, set clipping and draw S. */
2698 x_set_glyph_string_gc (s);
2699
2700 /* Draw relief (if any) in advance for char/composition so that the
2701 glyph string can be drawn over it. */
2702 if (!s->for_overlaps
2703 && s->face->box != FACE_NO_BOX
2704 && (s->first_glyph->type == CHAR_GLYPH
2705 || s->first_glyph->type == COMPOSITE_GLYPH))
2706
2707 {
2708 x_set_glyph_string_clipping (s);
2709 x_draw_glyph_string_background (s, 1);
2710 x_draw_glyph_string_box (s);
2711 x_set_glyph_string_clipping (s);
2712 relief_drawn_p = 1;
2713 }
2714 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2715 && !s->clip_tail
2716 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2717 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2718 /* We must clip just this glyph. left_overhang part has already
2719 drawn when s->prev was drawn, and right_overhang part will be
2720 drawn later when s->next is drawn. */
2721 x_set_glyph_string_clipping_exactly (s, s);
2722 else
2723 x_set_glyph_string_clipping (s);
2724
2725 switch (s->first_glyph->type)
2726 {
2727 case IMAGE_GLYPH:
2728 x_draw_image_glyph_string (s);
2729 break;
2730
2731 case STRETCH_GLYPH:
2732 x_draw_stretch_glyph_string (s);
2733 break;
2734
2735 case CHAR_GLYPH:
2736 if (s->for_overlaps)
2737 s->background_filled_p = 1;
2738 else
2739 x_draw_glyph_string_background (s, 0);
2740 x_draw_glyph_string_foreground (s);
2741 break;
2742
2743 case COMPOSITE_GLYPH:
2744 if (s->for_overlaps || (s->cmp_from > 0
2745 && ! s->first_glyph->u.cmp.automatic))
2746 s->background_filled_p = 1;
2747 else
2748 x_draw_glyph_string_background (s, 1);
2749 x_draw_composite_glyph_string_foreground (s);
2750 break;
2751
2752 case GLYPHLESS_GLYPH:
2753 if (s->for_overlaps)
2754 s->background_filled_p = 1;
2755 else
2756 x_draw_glyph_string_background (s, 1);
2757 x_draw_glyphless_glyph_string_foreground (s);
2758 break;
2759
2760 default:
2761 emacs_abort ();
2762 }
2763
2764 if (!s->for_overlaps)
2765 {
2766 /* Draw underline. */
2767 if (s->face->underline_p)
2768 {
2769 if (s->face->underline_type == FACE_UNDER_WAVE)
2770 {
2771 if (s->face->underline_defaulted_p)
2772 x_draw_underwave (s);
2773 else
2774 {
2775 XGCValues xgcv;
2776 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2777 XSetForeground (s->display, s->gc, s->face->underline_color);
2778 x_draw_underwave (s);
2779 XSetForeground (s->display, s->gc, xgcv.foreground);
2780 }
2781 }
2782 else if (s->face->underline_type == FACE_UNDER_LINE)
2783 {
2784 unsigned long thickness, position;
2785 int y;
2786
2787 if (s->prev && s->prev->face->underline_p
2788 && s->prev->face->underline_type == FACE_UNDER_LINE)
2789 {
2790 /* We use the same underline style as the previous one. */
2791 thickness = s->prev->underline_thickness;
2792 position = s->prev->underline_position;
2793 }
2794 else
2795 {
2796 /* Get the underline thickness. Default is 1 pixel. */
2797 if (s->font && s->font->underline_thickness > 0)
2798 thickness = s->font->underline_thickness;
2799 else
2800 thickness = 1;
2801 if (x_underline_at_descent_line)
2802 position = (s->height - thickness) - (s->ybase - s->y);
2803 else
2804 {
2805 /* Get the underline position. This is the recommended
2806 vertical offset in pixels from the baseline to the top of
2807 the underline. This is a signed value according to the
2808 specs, and its default is
2809
2810 ROUND ((maximum descent) / 2), with
2811 ROUND(x) = floor (x + 0.5) */
2812
2813 if (x_use_underline_position_properties
2814 && s->font && s->font->underline_position >= 0)
2815 position = s->font->underline_position;
2816 else if (s->font)
2817 position = (s->font->descent + 1) / 2;
2818 else
2819 position = underline_minimum_offset;
2820 }
2821 position = max (position, underline_minimum_offset);
2822 }
2823 /* Check the sanity of thickness and position. We should
2824 avoid drawing underline out of the current line area. */
2825 if (s->y + s->height <= s->ybase + position)
2826 position = (s->height - 1) - (s->ybase - s->y);
2827 if (s->y + s->height < s->ybase + position + thickness)
2828 thickness = (s->y + s->height) - (s->ybase + position);
2829 s->underline_thickness = thickness;
2830 s->underline_position = position;
2831 y = s->ybase + position;
2832 if (s->face->underline_defaulted_p)
2833 XFillRectangle (s->display, s->window, s->gc,
2834 s->x, y, s->width, thickness);
2835 else
2836 {
2837 XGCValues xgcv;
2838 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2839 XSetForeground (s->display, s->gc, s->face->underline_color);
2840 XFillRectangle (s->display, s->window, s->gc,
2841 s->x, y, s->width, thickness);
2842 XSetForeground (s->display, s->gc, xgcv.foreground);
2843 }
2844 }
2845 }
2846 /* Draw overline. */
2847 if (s->face->overline_p)
2848 {
2849 unsigned long dy = 0, h = 1;
2850
2851 if (s->face->overline_color_defaulted_p)
2852 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2853 s->width, h);
2854 else
2855 {
2856 XGCValues xgcv;
2857 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2858 XSetForeground (s->display, s->gc, s->face->overline_color);
2859 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2860 s->width, h);
2861 XSetForeground (s->display, s->gc, xgcv.foreground);
2862 }
2863 }
2864
2865 /* Draw strike-through. */
2866 if (s->face->strike_through_p)
2867 {
2868 unsigned long h = 1;
2869 unsigned long dy = (s->height - h) / 2;
2870
2871 if (s->face->strike_through_color_defaulted_p)
2872 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2873 s->width, h);
2874 else
2875 {
2876 XGCValues xgcv;
2877 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2878 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2879 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2880 s->width, h);
2881 XSetForeground (s->display, s->gc, xgcv.foreground);
2882 }
2883 }
2884
2885 /* Draw relief if not yet drawn. */
2886 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2887 x_draw_glyph_string_box (s);
2888
2889 if (s->prev)
2890 {
2891 struct glyph_string *prev;
2892
2893 for (prev = s->prev; prev; prev = prev->prev)
2894 if (prev->hl != s->hl
2895 && prev->x + prev->width + prev->right_overhang > s->x)
2896 {
2897 /* As prev was drawn while clipped to its own area, we
2898 must draw the right_overhang part using s->hl now. */
2899 enum draw_glyphs_face save = prev->hl;
2900
2901 prev->hl = s->hl;
2902 x_set_glyph_string_gc (prev);
2903 x_set_glyph_string_clipping_exactly (s, prev);
2904 if (prev->first_glyph->type == CHAR_GLYPH)
2905 x_draw_glyph_string_foreground (prev);
2906 else
2907 x_draw_composite_glyph_string_foreground (prev);
2908 XSetClipMask (prev->display, prev->gc, None);
2909 prev->hl = save;
2910 prev->num_clips = 0;
2911 }
2912 }
2913
2914 if (s->next)
2915 {
2916 struct glyph_string *next;
2917
2918 for (next = s->next; next; next = next->next)
2919 if (next->hl != s->hl
2920 && next->x - next->left_overhang < s->x + s->width)
2921 {
2922 /* As next will be drawn while clipped to its own area,
2923 we must draw the left_overhang part using s->hl now. */
2924 enum draw_glyphs_face save = next->hl;
2925
2926 next->hl = s->hl;
2927 x_set_glyph_string_gc (next);
2928 x_set_glyph_string_clipping_exactly (s, next);
2929 if (next->first_glyph->type == CHAR_GLYPH)
2930 x_draw_glyph_string_foreground (next);
2931 else
2932 x_draw_composite_glyph_string_foreground (next);
2933 XSetClipMask (next->display, next->gc, None);
2934 next->hl = save;
2935 next->num_clips = 0;
2936 next->clip_head = s->next;
2937 }
2938 }
2939 }
2940
2941 /* Reset clipping. */
2942 XSetClipMask (s->display, s->gc, None);
2943 s->num_clips = 0;
2944 }
2945
2946 /* Shift display to make room for inserted glyphs. */
2947
2948 static void
2949 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
2950 {
2951 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2952 f->output_data.x->normal_gc,
2953 x, y, width, height,
2954 x + shift_by, y);
2955 }
2956
2957 /* Delete N glyphs at the nominal cursor position. Not implemented
2958 for X frames. */
2959
2960 static void
2961 x_delete_glyphs (struct frame *f, register int n)
2962 {
2963 emacs_abort ();
2964 }
2965
2966
2967 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2968 If they are <= 0, this is probably an error. */
2969
2970 void
2971 x_clear_area (Display *dpy, Window window, int x, int y, int width, int height, int exposures)
2972 {
2973 eassert (width > 0 && height > 0);
2974 XClearArea (dpy, window, x, y, width, height, exposures);
2975 }
2976
2977
2978 /* Clear an entire frame. */
2979
2980 static void
2981 x_clear_frame (struct frame *f)
2982 {
2983 /* Clearing the frame will erase any cursor, so mark them all as no
2984 longer visible. */
2985 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2986 output_cursor.hpos = output_cursor.vpos = 0;
2987 output_cursor.x = -1;
2988
2989 /* We don't set the output cursor here because there will always
2990 follow an explicit cursor_to. */
2991 block_input ();
2992
2993 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
2994
2995 /* We have to clear the scroll bars. If we have changed colors or
2996 something like that, then they should be notified. */
2997 x_scroll_bar_clear (f);
2998
2999 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
3000 /* Make sure scroll bars are redrawn. As they aren't redrawn by
3001 redisplay, do it here. */
3002 if (FRAME_GTK_WIDGET (f))
3003 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
3004 #endif
3005
3006 XFlush (FRAME_X_DISPLAY (f));
3007
3008 unblock_input ();
3009 }
3010
3011
3012 \f
3013 /* Invert the middle quarter of the frame for .15 sec. */
3014
3015 static void
3016 XTflash (struct frame *f)
3017 {
3018 block_input ();
3019
3020 {
3021 #ifdef USE_GTK
3022 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3023 when the scroll bars and the edit widget share the same X window. */
3024 GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
3025 #ifdef HAVE_GTK3
3026 cairo_t *cr = gdk_cairo_create (window);
3027 cairo_set_source_rgb (cr, 1, 1, 1);
3028 cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
3029 #define XFillRectangle(d, win, gc, x, y, w, h) \
3030 do { \
3031 cairo_rectangle (cr, x, y, w, h); \
3032 cairo_fill (cr); \
3033 } \
3034 while (0)
3035 #else /* ! HAVE_GTK3 */
3036 GdkGCValues vals;
3037 GdkGC *gc;
3038 vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
3039 ^ FRAME_BACKGROUND_PIXEL (f));
3040 vals.function = GDK_XOR;
3041 gc = gdk_gc_new_with_values (window,
3042 &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
3043 #define XFillRectangle(d, win, gc, x, y, w, h) \
3044 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
3045 #endif /* ! HAVE_GTK3 */
3046 #else /* ! USE_GTK */
3047 GC gc;
3048
3049 /* Create a GC that will use the GXxor function to flip foreground
3050 pixels into background pixels. */
3051 {
3052 XGCValues values;
3053
3054 values.function = GXxor;
3055 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
3056 ^ FRAME_BACKGROUND_PIXEL (f));
3057
3058 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3059 GCFunction | GCForeground, &values);
3060 }
3061 #endif
3062 {
3063 /* Get the height not including a menu bar widget. */
3064 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3065 /* Height of each line to flash. */
3066 int flash_height = FRAME_LINE_HEIGHT (f);
3067 /* These will be the left and right margins of the rectangles. */
3068 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3069 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3070
3071 int width;
3072
3073 /* Don't flash the area between a scroll bar and the frame
3074 edge it is next to. */
3075 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3076 {
3077 case vertical_scroll_bar_left:
3078 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3079 break;
3080
3081 case vertical_scroll_bar_right:
3082 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3083 break;
3084
3085 default:
3086 break;
3087 }
3088
3089 width = flash_right - flash_left;
3090
3091 /* If window is tall, flash top and bottom line. */
3092 if (height > 3 * FRAME_LINE_HEIGHT (f))
3093 {
3094 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3095 flash_left,
3096 (FRAME_INTERNAL_BORDER_WIDTH (f)
3097 + FRAME_TOP_MARGIN_HEIGHT (f)),
3098 width, flash_height);
3099 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3100 flash_left,
3101 (height - flash_height
3102 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3103 width, flash_height);
3104
3105 }
3106 else
3107 /* If it is short, flash it all. */
3108 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3109 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3110 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3111
3112 x_flush (f);
3113
3114 {
3115 EMACS_TIME delay = make_emacs_time (0, 150 * 1000 * 1000);
3116 EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), delay);
3117
3118 /* Keep waiting until past the time wakeup or any input gets
3119 available. */
3120 while (! detect_input_pending ())
3121 {
3122 EMACS_TIME current = current_emacs_time ();
3123 EMACS_TIME timeout;
3124
3125 /* Break if result would not be positive. */
3126 if (EMACS_TIME_LE (wakeup, current))
3127 break;
3128
3129 /* How long `select' should wait. */
3130 timeout = make_emacs_time (0, 10 * 1000 * 1000);
3131
3132 /* Try to wait that long--but we might wake up sooner. */
3133 pselect (0, NULL, NULL, NULL, &timeout, NULL);
3134 }
3135 }
3136
3137 /* If window is tall, flash top and bottom line. */
3138 if (height > 3 * FRAME_LINE_HEIGHT (f))
3139 {
3140 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3141 flash_left,
3142 (FRAME_INTERNAL_BORDER_WIDTH (f)
3143 + FRAME_TOP_MARGIN_HEIGHT (f)),
3144 width, flash_height);
3145 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3146 flash_left,
3147 (height - flash_height
3148 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3149 width, flash_height);
3150 }
3151 else
3152 /* If it is short, flash it all. */
3153 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3154 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3155 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3156
3157 #ifdef USE_GTK
3158 #ifdef HAVE_GTK3
3159 cairo_destroy (cr);
3160 #else
3161 g_object_unref (G_OBJECT (gc));
3162 #endif
3163 #undef XFillRectangle
3164 #else
3165 XFreeGC (FRAME_X_DISPLAY (f), gc);
3166 #endif
3167 x_flush (f);
3168 }
3169 }
3170
3171 unblock_input ();
3172 }
3173
3174
3175 static void
3176 XTtoggle_invisible_pointer (struct frame *f, int invisible)
3177 {
3178 block_input ();
3179 if (invisible)
3180 {
3181 if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
3182 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3183 FRAME_X_DISPLAY_INFO (f)->invisible_cursor);
3184 }
3185 else
3186 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3187 f->output_data.x->current_cursor);
3188 f->pointer_invisible = invisible;
3189 unblock_input ();
3190 }
3191
3192
3193 /* Make audible bell. */
3194
3195 static void
3196 XTring_bell (struct frame *f)
3197 {
3198 if (FRAME_X_DISPLAY (f))
3199 {
3200 if (visible_bell)
3201 XTflash (f);
3202 else
3203 {
3204 block_input ();
3205 #ifdef HAVE_XKB
3206 XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
3207 #else
3208 XBell (FRAME_X_DISPLAY (f), 0);
3209 #endif
3210 XFlush (FRAME_X_DISPLAY (f));
3211 unblock_input ();
3212 }
3213 }
3214 }
3215
3216 \f
3217 /* Specify how many text lines, from the top of the window,
3218 should be affected by insert-lines and delete-lines operations.
3219 This, and those operations, are used only within an update
3220 that is bounded by calls to x_update_begin and x_update_end. */
3221
3222 static void
3223 XTset_terminal_window (struct frame *f, int n)
3224 {
3225 /* This function intentionally left blank. */
3226 }
3227
3228
3229 \f
3230 /***********************************************************************
3231 Line Dance
3232 ***********************************************************************/
3233
3234 /* Perform an insert-lines or delete-lines operation, inserting N
3235 lines or deleting -N lines at vertical position VPOS. */
3236
3237 static void
3238 x_ins_del_lines (struct frame *f, int vpos, int n)
3239 {
3240 emacs_abort ();
3241 }
3242
3243
3244 /* Scroll part of the display as described by RUN. */
3245
3246 static void
3247 x_scroll_run (struct window *w, struct run *run)
3248 {
3249 struct frame *f = XFRAME (w->frame);
3250 int x, y, width, height, from_y, to_y, bottom_y;
3251
3252 /* Get frame-relative bounding box of the text display area of W,
3253 without mode lines. Include in this box the left and right
3254 fringe of W. */
3255 window_box (w, -1, &x, &y, &width, &height);
3256
3257 #ifdef USE_TOOLKIT_SCROLL_BARS
3258 /* If the fringe is adjacent to the left (right) scroll bar of a
3259 leftmost (rightmost, respectively) window, then extend its
3260 background to the gap between the fringe and the bar. */
3261 if ((WINDOW_LEFTMOST_P (w)
3262 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3263 || (WINDOW_RIGHTMOST_P (w)
3264 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
3265 {
3266 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3267
3268 if (sb_width > 0)
3269 {
3270 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
3271 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
3272 * FRAME_COLUMN_WIDTH (f));
3273
3274 if (bar_area_x + bar_area_width == x)
3275 {
3276 x = bar_area_x + sb_width;
3277 width += bar_area_width - sb_width;
3278 }
3279 else if (x + width == bar_area_x)
3280 width += bar_area_width - sb_width;
3281 }
3282 }
3283 #endif
3284
3285 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3286 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3287 bottom_y = y + height;
3288
3289 if (to_y < from_y)
3290 {
3291 /* Scrolling up. Make sure we don't copy part of the mode
3292 line at the bottom. */
3293 if (from_y + run->height > bottom_y)
3294 height = bottom_y - from_y;
3295 else
3296 height = run->height;
3297 }
3298 else
3299 {
3300 /* Scrolling down. Make sure we don't copy over the mode line.
3301 at the bottom. */
3302 if (to_y + run->height > bottom_y)
3303 height = bottom_y - to_y;
3304 else
3305 height = run->height;
3306 }
3307
3308 block_input ();
3309
3310 /* Cursor off. Will be switched on again in x_update_window_end. */
3311 x_clear_cursor (w);
3312
3313 XCopyArea (FRAME_X_DISPLAY (f),
3314 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3315 f->output_data.x->normal_gc,
3316 x, from_y,
3317 width, height,
3318 x, to_y);
3319
3320 unblock_input ();
3321 }
3322
3323
3324 \f
3325 /***********************************************************************
3326 Exposure Events
3327 ***********************************************************************/
3328
3329 \f
3330 static void
3331 frame_highlight (struct frame *f)
3332 {
3333 /* We used to only do this if Vx_no_window_manager was non-nil, but
3334 the ICCCM (section 4.1.6) says that the window's border pixmap
3335 and border pixel are window attributes which are "private to the
3336 client", so we can always change it to whatever we want. */
3337 block_input ();
3338 /* I recently started to get errors in this XSetWindowBorder, depending on
3339 the window-manager in use, tho something more is at play since I've been
3340 using that same window-manager binary for ever. Let's not crash just
3341 because of this (bug#9310). */
3342 x_catch_errors (FRAME_X_DISPLAY (f));
3343 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3344 f->output_data.x->border_pixel);
3345 x_uncatch_errors ();
3346 unblock_input ();
3347 x_update_cursor (f, 1);
3348 x_set_frame_alpha (f);
3349 }
3350
3351 static void
3352 frame_unhighlight (struct frame *f)
3353 {
3354 /* We used to only do this if Vx_no_window_manager was non-nil, but
3355 the ICCCM (section 4.1.6) says that the window's border pixmap
3356 and border pixel are window attributes which are "private to the
3357 client", so we can always change it to whatever we want. */
3358 block_input ();
3359 /* Same as above for XSetWindowBorder (bug#9310). */
3360 x_catch_errors (FRAME_X_DISPLAY (f));
3361 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3362 f->output_data.x->border_tile);
3363 x_uncatch_errors ();
3364 unblock_input ();
3365 x_update_cursor (f, 1);
3366 x_set_frame_alpha (f);
3367 }
3368
3369 /* The focus has changed. Update the frames as necessary to reflect
3370 the new situation. Note that we can't change the selected frame
3371 here, because the Lisp code we are interrupting might become confused.
3372 Each event gets marked with the frame in which it occurred, so the
3373 Lisp code can tell when the switch took place by examining the events. */
3374
3375 static void
3376 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
3377 {
3378 struct frame *old_focus = dpyinfo->x_focus_frame;
3379
3380 if (frame != dpyinfo->x_focus_frame)
3381 {
3382 /* Set this before calling other routines, so that they see
3383 the correct value of x_focus_frame. */
3384 dpyinfo->x_focus_frame = frame;
3385
3386 if (old_focus && old_focus->auto_lower)
3387 x_lower_frame (old_focus);
3388
3389 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3390 pending_autoraise_frame = dpyinfo->x_focus_frame;
3391 else
3392 pending_autoraise_frame = 0;
3393 }
3394
3395 x_frame_rehighlight (dpyinfo);
3396 }
3397
3398 /* Handle FocusIn and FocusOut state changes for FRAME.
3399 If FRAME has focus and there exists more than one frame, puts
3400 a FOCUS_IN_EVENT into *BUFP. */
3401
3402 static void
3403 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
3404 {
3405 if (type == FocusIn)
3406 {
3407 if (dpyinfo->x_focus_event_frame != frame)
3408 {
3409 x_new_focus_frame (dpyinfo, frame);
3410 dpyinfo->x_focus_event_frame = frame;
3411
3412 /* Don't stop displaying the initial startup message
3413 for a switch-frame event we don't need. */
3414 /* When run as a daemon, Vterminal_frame is always NIL. */
3415 bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt))
3416 && CONSP (Vframe_list)
3417 && !NILP (XCDR (Vframe_list)))
3418 ? Qt : Qnil);
3419 bufp->kind = FOCUS_IN_EVENT;
3420 XSETFRAME (bufp->frame_or_window, frame);
3421 }
3422
3423 frame->output_data.x->focus_state |= state;
3424
3425 #ifdef HAVE_X_I18N
3426 if (FRAME_XIC (frame))
3427 XSetICFocus (FRAME_XIC (frame));
3428 #endif
3429 }
3430 else if (type == FocusOut)
3431 {
3432 frame->output_data.x->focus_state &= ~state;
3433
3434 if (dpyinfo->x_focus_event_frame == frame)
3435 {
3436 dpyinfo->x_focus_event_frame = 0;
3437 x_new_focus_frame (dpyinfo, 0);
3438
3439 bufp->kind = FOCUS_OUT_EVENT;
3440 XSETFRAME (bufp->frame_or_window, frame);
3441 }
3442
3443 #ifdef HAVE_X_I18N
3444 if (FRAME_XIC (frame))
3445 XUnsetICFocus (FRAME_XIC (frame));
3446 #endif
3447 if (frame->pointer_invisible)
3448 XTtoggle_invisible_pointer (frame, 0);
3449 }
3450 }
3451
3452 /* The focus may have changed. Figure out if it is a real focus change,
3453 by checking both FocusIn/Out and Enter/LeaveNotify events.
3454
3455 Returns FOCUS_IN_EVENT event in *BUFP. */
3456
3457 static void
3458 x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp)
3459 {
3460 struct frame *frame;
3461
3462 frame = x_any_window_to_frame (dpyinfo, event->xany.window);
3463 if (! frame)
3464 return;
3465
3466 switch (event->type)
3467 {
3468 case EnterNotify:
3469 case LeaveNotify:
3470 {
3471 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
3472 int focus_state
3473 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
3474
3475 if (event->xcrossing.detail != NotifyInferior
3476 && event->xcrossing.focus
3477 && ! (focus_state & FOCUS_EXPLICIT))
3478 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
3479 FOCUS_IMPLICIT,
3480 dpyinfo, frame, bufp);
3481 }
3482 break;
3483
3484 case FocusIn:
3485 case FocusOut:
3486 x_focus_changed (event->type,
3487 (event->xfocus.detail == NotifyPointer ?
3488 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3489 dpyinfo, frame, bufp);
3490 break;
3491
3492 case ClientMessage:
3493 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
3494 {
3495 enum xembed_message msg = event->xclient.data.l[1];
3496 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
3497 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
3498 }
3499 break;
3500 }
3501 }
3502
3503
3504 #if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
3505 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3506
3507 void
3508 x_mouse_leave (struct x_display_info *dpyinfo)
3509 {
3510 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3511 }
3512 #endif
3513
3514 /* The focus has changed, or we have redirected a frame's focus to
3515 another frame (this happens when a frame uses a surrogate
3516 mini-buffer frame). Shift the highlight as appropriate.
3517
3518 The FRAME argument doesn't necessarily have anything to do with which
3519 frame is being highlighted or un-highlighted; we only use it to find
3520 the appropriate X display info. */
3521
3522 static void
3523 XTframe_rehighlight (struct frame *frame)
3524 {
3525 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3526 }
3527
3528 static void
3529 x_frame_rehighlight (struct x_display_info *dpyinfo)
3530 {
3531 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3532
3533 if (dpyinfo->x_focus_frame)
3534 {
3535 dpyinfo->x_highlight_frame
3536 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3537 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3538 : dpyinfo->x_focus_frame);
3539 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3540 {
3541 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
3542 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3543 }
3544 }
3545 else
3546 dpyinfo->x_highlight_frame = 0;
3547
3548 if (dpyinfo->x_highlight_frame != old_highlight)
3549 {
3550 if (old_highlight)
3551 frame_unhighlight (old_highlight);
3552 if (dpyinfo->x_highlight_frame)
3553 frame_highlight (dpyinfo->x_highlight_frame);
3554 }
3555 }
3556
3557
3558 \f
3559 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3560
3561 /* Initialize mode_switch_bit and modifier_meaning. */
3562 static void
3563 x_find_modifier_meanings (struct x_display_info *dpyinfo)
3564 {
3565 int min_code, max_code;
3566 KeySym *syms;
3567 int syms_per_code;
3568 XModifierKeymap *mods;
3569
3570 dpyinfo->meta_mod_mask = 0;
3571 dpyinfo->shift_lock_mask = 0;
3572 dpyinfo->alt_mod_mask = 0;
3573 dpyinfo->super_mod_mask = 0;
3574 dpyinfo->hyper_mod_mask = 0;
3575
3576 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3577
3578 syms = XGetKeyboardMapping (dpyinfo->display,
3579 min_code, max_code - min_code + 1,
3580 &syms_per_code);
3581 mods = XGetModifierMapping (dpyinfo->display);
3582
3583 /* Scan the modifier table to see which modifier bits the Meta and
3584 Alt keysyms are on. */
3585 {
3586 int row, col; /* The row and column in the modifier table. */
3587 int found_alt_or_meta;
3588
3589 for (row = 3; row < 8; row++)
3590 {
3591 found_alt_or_meta = 0;
3592 for (col = 0; col < mods->max_keypermod; col++)
3593 {
3594 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
3595
3596 /* Zeroes are used for filler. Skip them. */
3597 if (code == 0)
3598 continue;
3599
3600 /* Are any of this keycode's keysyms a meta key? */
3601 {
3602 int code_col;
3603
3604 for (code_col = 0; code_col < syms_per_code; code_col++)
3605 {
3606 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3607
3608 switch (sym)
3609 {
3610 case XK_Meta_L:
3611 case XK_Meta_R:
3612 found_alt_or_meta = 1;
3613 dpyinfo->meta_mod_mask |= (1 << row);
3614 break;
3615
3616 case XK_Alt_L:
3617 case XK_Alt_R:
3618 found_alt_or_meta = 1;
3619 dpyinfo->alt_mod_mask |= (1 << row);
3620 break;
3621
3622 case XK_Hyper_L:
3623 case XK_Hyper_R:
3624 if (!found_alt_or_meta)
3625 dpyinfo->hyper_mod_mask |= (1 << row);
3626 code_col = syms_per_code;
3627 col = mods->max_keypermod;
3628 break;
3629
3630 case XK_Super_L:
3631 case XK_Super_R:
3632 if (!found_alt_or_meta)
3633 dpyinfo->super_mod_mask |= (1 << row);
3634 code_col = syms_per_code;
3635 col = mods->max_keypermod;
3636 break;
3637
3638 case XK_Shift_Lock:
3639 /* Ignore this if it's not on the lock modifier. */
3640 if (!found_alt_or_meta && ((1 << row) == LockMask))
3641 dpyinfo->shift_lock_mask = LockMask;
3642 code_col = syms_per_code;
3643 col = mods->max_keypermod;
3644 break;
3645 }
3646 }
3647 }
3648 }
3649 }
3650 }
3651
3652 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3653 if (! dpyinfo->meta_mod_mask)
3654 {
3655 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3656 dpyinfo->alt_mod_mask = 0;
3657 }
3658
3659 /* If some keys are both alt and meta,
3660 make them just meta, not alt. */
3661 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3662 {
3663 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3664 }
3665
3666 XFree (syms);
3667 XFreeModifiermap (mods);
3668 }
3669
3670 /* Convert between the modifier bits X uses and the modifier bits
3671 Emacs uses. */
3672
3673 int
3674 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
3675 {
3676 int mod_meta = meta_modifier;
3677 int mod_alt = alt_modifier;
3678 int mod_hyper = hyper_modifier;
3679 int mod_super = super_modifier;
3680 Lisp_Object tem;
3681
3682 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3683 if (INTEGERP (tem)) mod_alt = XINT (tem) & INT_MAX;
3684 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3685 if (INTEGERP (tem)) mod_meta = XINT (tem) & INT_MAX;
3686 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3687 if (INTEGERP (tem)) mod_hyper = XINT (tem) & INT_MAX;
3688 tem = Fget (Vx_super_keysym, Qmodifier_value);
3689 if (INTEGERP (tem)) mod_super = XINT (tem) & INT_MAX;
3690
3691 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3692 | ((state & ControlMask) ? ctrl_modifier : 0)
3693 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
3694 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
3695 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
3696 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
3697 }
3698
3699 static int
3700 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, EMACS_INT state)
3701 {
3702 EMACS_INT mod_meta = meta_modifier;
3703 EMACS_INT mod_alt = alt_modifier;
3704 EMACS_INT mod_hyper = hyper_modifier;
3705 EMACS_INT mod_super = super_modifier;
3706
3707 Lisp_Object tem;
3708
3709 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3710 if (INTEGERP (tem)) mod_alt = XINT (tem);
3711 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3712 if (INTEGERP (tem)) mod_meta = XINT (tem);
3713 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3714 if (INTEGERP (tem)) mod_hyper = XINT (tem);
3715 tem = Fget (Vx_super_keysym, Qmodifier_value);
3716 if (INTEGERP (tem)) mod_super = XINT (tem);
3717
3718
3719 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
3720 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
3721 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
3722 | ((state & shift_modifier) ? ShiftMask : 0)
3723 | ((state & ctrl_modifier) ? ControlMask : 0)
3724 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
3725 }
3726
3727 /* Convert a keysym to its name. */
3728
3729 char *
3730 x_get_keysym_name (int keysym)
3731 {
3732 char *value;
3733
3734 block_input ();
3735 value = XKeysymToString (keysym);
3736 unblock_input ();
3737
3738 return value;
3739 }
3740
3741
3742 \f
3743 /* Mouse clicks and mouse movement. Rah. */
3744
3745 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3746
3747 If the event is a button press, then note that we have grabbed
3748 the mouse. */
3749
3750 static Lisp_Object
3751 construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f)
3752 {
3753 /* Make the event type NO_EVENT; we'll change that when we decide
3754 otherwise. */
3755 result->kind = MOUSE_CLICK_EVENT;
3756 result->code = event->button - Button1;
3757 result->timestamp = event->time;
3758 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3759 event->state)
3760 | (event->type == ButtonRelease
3761 ? up_modifier
3762 : down_modifier));
3763
3764 XSETINT (result->x, event->x);
3765 XSETINT (result->y, event->y);
3766 XSETFRAME (result->frame_or_window, f);
3767 result->arg = Qnil;
3768 return Qnil;
3769 }
3770
3771 \f
3772 /* Function to report a mouse movement to the mainstream Emacs code.
3773 The input handler calls this.
3774
3775 We have received a mouse movement event, which is given in *event.
3776 If the mouse is over a different glyph than it was last time, tell
3777 the mainstream emacs code by setting mouse_moved. If not, ask for
3778 another motion event, so we can check again the next time it moves. */
3779
3780 static XMotionEvent last_mouse_motion_event;
3781 static Lisp_Object last_mouse_motion_frame;
3782
3783 static int
3784 note_mouse_movement (struct frame *frame, XMotionEvent *event)
3785 {
3786 last_mouse_movement_time = event->time;
3787 last_mouse_motion_event = *event;
3788 XSETFRAME (last_mouse_motion_frame, frame);
3789
3790 if (!FRAME_X_OUTPUT (frame))
3791 return 0;
3792
3793 if (event->window != FRAME_X_WINDOW (frame))
3794 {
3795 frame->mouse_moved = 1;
3796 last_mouse_scroll_bar = Qnil;
3797 note_mouse_highlight (frame, -1, -1);
3798 last_mouse_glyph_frame = 0;
3799 return 1;
3800 }
3801
3802
3803 /* Has the mouse moved off the glyph it was on at the last sighting? */
3804 if (frame != last_mouse_glyph_frame
3805 || event->x < last_mouse_glyph.x
3806 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
3807 || event->y < last_mouse_glyph.y
3808 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
3809 {
3810 frame->mouse_moved = 1;
3811 last_mouse_scroll_bar = Qnil;
3812 note_mouse_highlight (frame, event->x, event->y);
3813 /* Remember which glyph we're now on. */
3814 remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
3815 last_mouse_glyph_frame = frame;
3816 return 1;
3817 }
3818
3819 return 0;
3820 }
3821
3822 \f
3823 /************************************************************************
3824 Mouse Face
3825 ************************************************************************/
3826
3827 static void
3828 redo_mouse_highlight (void)
3829 {
3830 if (!NILP (last_mouse_motion_frame)
3831 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3832 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3833 last_mouse_motion_event.x,
3834 last_mouse_motion_event.y);
3835 }
3836
3837
3838
3839 /* Return the current position of the mouse.
3840 *FP should be a frame which indicates which display to ask about.
3841
3842 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3843 and *PART to the frame, window, and scroll bar part that the mouse
3844 is over. Set *X and *Y to the portion and whole of the mouse's
3845 position on the scroll bar.
3846
3847 If the mouse movement started elsewhere, set *FP to the frame the
3848 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3849 the mouse is over.
3850
3851 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
3852 was at this position.
3853
3854 Don't store anything if we don't have a valid set of values to report.
3855
3856 This clears the mouse_moved flag, so we can wait for the next mouse
3857 movement. */
3858
3859 static void
3860 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3861 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3862 Time *timestamp)
3863 {
3864 struct frame *f1;
3865
3866 block_input ();
3867
3868 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3869 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3870 else
3871 {
3872 Window root;
3873 int root_x, root_y;
3874
3875 Window dummy_window;
3876 int dummy;
3877
3878 Lisp_Object frame, tail;
3879
3880 /* Clear the mouse-moved flag for every frame on this display. */
3881 FOR_EACH_FRAME (tail, frame)
3882 if (FRAME_X_P (XFRAME (frame))
3883 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
3884 XFRAME (frame)->mouse_moved = 0;
3885
3886 last_mouse_scroll_bar = Qnil;
3887
3888 /* Figure out which root window we're on. */
3889 XQueryPointer (FRAME_X_DISPLAY (*fp),
3890 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
3891
3892 /* The root window which contains the pointer. */
3893 &root,
3894
3895 /* Trash which we can't trust if the pointer is on
3896 a different screen. */
3897 &dummy_window,
3898
3899 /* The position on that root window. */
3900 &root_x, &root_y,
3901
3902 /* More trash we can't trust. */
3903 &dummy, &dummy,
3904
3905 /* Modifier keys and pointer buttons, about which
3906 we don't care. */
3907 (unsigned int *) &dummy);
3908
3909 /* Now we have a position on the root; find the innermost window
3910 containing the pointer. */
3911 {
3912 Window win, child;
3913 int win_x, win_y;
3914 int parent_x = 0, parent_y = 0;
3915
3916 win = root;
3917
3918 /* XTranslateCoordinates can get errors if the window
3919 structure is changing at the same time this function
3920 is running. So at least we must not crash from them. */
3921
3922 x_catch_errors (FRAME_X_DISPLAY (*fp));
3923
3924 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3925 && FRAME_LIVE_P (last_mouse_frame))
3926 {
3927 /* If mouse was grabbed on a frame, give coords for that frame
3928 even if the mouse is now outside it. */
3929 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3930
3931 /* From-window, to-window. */
3932 root, FRAME_X_WINDOW (last_mouse_frame),
3933
3934 /* From-position, to-position. */
3935 root_x, root_y, &win_x, &win_y,
3936
3937 /* Child of win. */
3938 &child);
3939 f1 = last_mouse_frame;
3940 }
3941 else
3942 {
3943 while (1)
3944 {
3945 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
3946
3947 /* From-window, to-window. */
3948 root, win,
3949
3950 /* From-position, to-position. */
3951 root_x, root_y, &win_x, &win_y,
3952
3953 /* Child of win. */
3954 &child);
3955
3956 if (child == None || child == win)
3957 break;
3958 #ifdef USE_GTK
3959 /* We don't wan't to know the innermost window. We
3960 want the edit window. For non-Gtk+ the innermost
3961 window is the edit window. For Gtk+ it might not
3962 be. It might be the tool bar for example. */
3963 if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win))
3964 break;
3965 #endif
3966 win = child;
3967 parent_x = win_x;
3968 parent_y = win_y;
3969 }
3970
3971 /* Now we know that:
3972 win is the innermost window containing the pointer
3973 (XTC says it has no child containing the pointer),
3974 win_x and win_y are the pointer's position in it
3975 (XTC did this the last time through), and
3976 parent_x and parent_y are the pointer's position in win's parent.
3977 (They are what win_x and win_y were when win was child.
3978 If win is the root window, it has no parent, and
3979 parent_{x,y} are invalid, but that's okay, because we'll
3980 never use them in that case.) */
3981
3982 #ifdef USE_GTK
3983 /* We don't wan't to know the innermost window. We
3984 want the edit window. */
3985 f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
3986 #else
3987 /* Is win one of our frames? */
3988 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
3989 #endif
3990
3991 #ifdef USE_X_TOOLKIT
3992 /* If we end up with the menu bar window, say it's not
3993 on the frame. */
3994 if (f1 != NULL
3995 && f1->output_data.x->menubar_widget
3996 && win == XtWindow (f1->output_data.x->menubar_widget))
3997 f1 = NULL;
3998 #endif /* USE_X_TOOLKIT */
3999 }
4000
4001 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
4002 f1 = 0;
4003
4004 x_uncatch_errors ();
4005
4006 /* If not, is it one of our scroll bars? */
4007 if (! f1)
4008 {
4009 struct scroll_bar *bar;
4010
4011 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
4012
4013 if (bar)
4014 {
4015 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4016 win_x = parent_x;
4017 win_y = parent_y;
4018 }
4019 }
4020
4021 if (f1 == 0 && insist > 0)
4022 f1 = SELECTED_FRAME ();
4023
4024 if (f1)
4025 {
4026 /* Ok, we found a frame. Store all the values.
4027 last_mouse_glyph is a rectangle used to reduce the
4028 generation of mouse events. To not miss any motion
4029 events, we must divide the frame into rectangles of the
4030 size of the smallest character that could be displayed
4031 on it, i.e. into the same rectangles that matrices on
4032 the frame are divided into. */
4033
4034 remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
4035 last_mouse_glyph_frame = f1;
4036
4037 *bar_window = Qnil;
4038 *part = 0;
4039 *fp = f1;
4040 XSETINT (*x, win_x);
4041 XSETINT (*y, win_y);
4042 *timestamp = last_mouse_movement_time;
4043 }
4044 }
4045 }
4046
4047 unblock_input ();
4048 }
4049
4050
4051 \f
4052 /***********************************************************************
4053 Scroll bars
4054 ***********************************************************************/
4055
4056 /* Scroll bar support. */
4057
4058 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4059 manages it.
4060 This can be called in GC, so we have to make sure to strip off mark
4061 bits. */
4062
4063 static struct scroll_bar *
4064 x_window_to_scroll_bar (Display *display, Window window_id)
4065 {
4066 Lisp_Object tail, frame;
4067
4068 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4069 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
4070 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4071
4072 FOR_EACH_FRAME (tail, frame)
4073 {
4074 Lisp_Object bar, condemned;
4075
4076 if (! FRAME_X_P (XFRAME (frame)))
4077 continue;
4078
4079 /* Scan this frame's scroll bar list for a scroll bar with the
4080 right window ID. */
4081 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
4082 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
4083 /* This trick allows us to search both the ordinary and
4084 condemned scroll bar lists with one loop. */
4085 ! NILP (bar) || (bar = condemned,
4086 condemned = Qnil,
4087 ! NILP (bar));
4088 bar = XSCROLL_BAR (bar)->next)
4089 if (XSCROLL_BAR (bar)->x_window == window_id &&
4090 FRAME_X_DISPLAY (XFRAME (frame)) == display)
4091 return XSCROLL_BAR (bar);
4092 }
4093
4094 return NULL;
4095 }
4096
4097
4098 #if defined USE_LUCID
4099
4100 /* Return the Lucid menu bar WINDOW is part of. Return null
4101 if WINDOW is not part of a menu bar. */
4102
4103 static Widget
4104 x_window_to_menu_bar (Window window)
4105 {
4106 Lisp_Object tail, frame;
4107
4108 FOR_EACH_FRAME (tail, frame)
4109 if (FRAME_X_P (XFRAME (frame)))
4110 {
4111 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
4112
4113 if (menu_bar && xlwmenu_window_p (menu_bar, window))
4114 return menu_bar;
4115 }
4116 return NULL;
4117 }
4118
4119 #endif /* USE_LUCID */
4120
4121 \f
4122 /************************************************************************
4123 Toolkit scroll bars
4124 ************************************************************************/
4125
4126 #ifdef USE_TOOLKIT_SCROLL_BARS
4127
4128 static void x_scroll_bar_to_input_event (XEvent *, struct input_event *);
4129 static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
4130 static void x_create_toolkit_scroll_bar (struct frame *,
4131 struct scroll_bar *);
4132 static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *,
4133 int, int, int);
4134
4135
4136 /* Lisp window being scrolled. Set when starting to interact with
4137 a toolkit scroll bar, reset to nil when ending the interaction. */
4138
4139 static Lisp_Object window_being_scrolled;
4140
4141 /* Last scroll bar part sent in xm_scroll_callback. */
4142
4143 static int last_scroll_bar_part;
4144
4145 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4146 that movements of 1/20 of the screen size are mapped to up/down. */
4147
4148 #ifndef USE_GTK
4149 /* Id of action hook installed for scroll bars. */
4150
4151 static XtActionHookId action_hook_id;
4152
4153 static Boolean xaw3d_arrow_scroll;
4154
4155 /* Whether the drag scrolling maintains the mouse at the top of the
4156 thumb. If not, resizing the thumb needs to be done more carefully
4157 to avoid jerkiness. */
4158
4159 static Boolean xaw3d_pick_top;
4160
4161 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4162 bars are used.. The hook is responsible for detecting when
4163 the user ends an interaction with the scroll bar, and generates
4164 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4165
4166 static void
4167 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4168 XEvent *event, String *params, Cardinal *num_params)
4169 {
4170 int scroll_bar_p;
4171 const char *end_action;
4172
4173 #ifdef USE_MOTIF
4174 scroll_bar_p = XmIsScrollBar (widget);
4175 end_action = "Release";
4176 #else /* !USE_MOTIF i.e. use Xaw */
4177 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4178 end_action = "EndScroll";
4179 #endif /* USE_MOTIF */
4180
4181 if (scroll_bar_p
4182 && strcmp (action_name, end_action) == 0
4183 && WINDOWP (window_being_scrolled))
4184 {
4185 struct window *w;
4186
4187 x_send_scroll_bar_event (window_being_scrolled,
4188 scroll_bar_end_scroll, 0, 0);
4189 w = XWINDOW (window_being_scrolled);
4190
4191 if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
4192 {
4193 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
4194 /* The thumb size is incorrect while dragging: fix it. */
4195 set_vertical_scroll_bar (w);
4196 }
4197 window_being_scrolled = Qnil;
4198 last_scroll_bar_part = -1;
4199
4200 /* Xt timeouts no longer needed. */
4201 toolkit_scroll_bar_interaction = 0;
4202 }
4203 }
4204 #endif /* not USE_GTK */
4205
4206 /* A vector of windows used for communication between
4207 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
4208
4209 static struct window **scroll_bar_windows;
4210 static ptrdiff_t scroll_bar_windows_size;
4211
4212
4213 /* Send a client message with message type Xatom_Scrollbar for a
4214 scroll action to the frame of WINDOW. PART is a value identifying
4215 the part of the scroll bar that was clicked on. PORTION is the
4216 amount to scroll of a whole of WHOLE. */
4217
4218 static void
4219 x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
4220 {
4221 XEvent event;
4222 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
4223 struct window *w = XWINDOW (window);
4224 struct frame *f = XFRAME (w->frame);
4225 ptrdiff_t i;
4226
4227 block_input ();
4228
4229 /* Construct a ClientMessage event to send to the frame. */
4230 ev->type = ClientMessage;
4231 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
4232 ev->display = FRAME_X_DISPLAY (f);
4233 ev->window = FRAME_X_WINDOW (f);
4234 ev->format = 32;
4235
4236 /* We can only transfer 32 bits in the XClientMessageEvent, which is
4237 not enough to store a pointer or Lisp_Object on a 64 bit system.
4238 So, store the window in scroll_bar_windows and pass the index
4239 into that array in the event. */
4240 for (i = 0; i < scroll_bar_windows_size; ++i)
4241 if (scroll_bar_windows[i] == NULL)
4242 break;
4243
4244 if (i == scroll_bar_windows_size)
4245 {
4246 ptrdiff_t old_nbytes =
4247 scroll_bar_windows_size * sizeof *scroll_bar_windows;
4248 ptrdiff_t nbytes;
4249 enum { XClientMessageEvent_MAX = 0x7fffffff };
4250 scroll_bar_windows =
4251 xpalloc (scroll_bar_windows, &scroll_bar_windows_size, 1,
4252 XClientMessageEvent_MAX, sizeof *scroll_bar_windows);
4253 nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4254 memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);
4255 }
4256
4257 scroll_bar_windows[i] = w;
4258 ev->data.l[0] = (long) i;
4259 ev->data.l[1] = (long) part;
4260 ev->data.l[2] = (long) 0;
4261 ev->data.l[3] = (long) portion;
4262 ev->data.l[4] = (long) whole;
4263
4264 /* Make Xt timeouts work while the scroll bar is active. */
4265 #ifdef USE_X_TOOLKIT
4266 toolkit_scroll_bar_interaction = 1;
4267 x_activate_timeout_atimer ();
4268 #endif
4269
4270 /* Setting the event mask to zero means that the message will
4271 be sent to the client that created the window, and if that
4272 window no longer exists, no event will be sent. */
4273 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
4274 unblock_input ();
4275 }
4276
4277
4278 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4279 in *IEVENT. */
4280
4281 static void
4282 x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
4283 {
4284 XClientMessageEvent *ev = (XClientMessageEvent *) event;
4285 Lisp_Object window;
4286 struct window *w;
4287
4288 w = scroll_bar_windows[ev->data.l[0]];
4289 scroll_bar_windows[ev->data.l[0]] = NULL;
4290
4291 XSETWINDOW (window, w);
4292
4293 ievent->kind = SCROLL_BAR_CLICK_EVENT;
4294 ievent->frame_or_window = window;
4295 ievent->arg = Qnil;
4296 #ifdef USE_GTK
4297 ievent->timestamp = CurrentTime;
4298 #else
4299 ievent->timestamp =
4300 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
4301 #endif
4302 ievent->part = ev->data.l[1];
4303 ievent->code = ev->data.l[2];
4304 ievent->x = make_number ((int) ev->data.l[3]);
4305 ievent->y = make_number ((int) ev->data.l[4]);
4306 ievent->modifiers = 0;
4307 }
4308
4309
4310 #ifdef USE_MOTIF
4311
4312 /* Minimum and maximum values used for Motif scroll bars. */
4313
4314 #define XM_SB_MAX 10000000
4315
4316
4317 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4318 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4319 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4320
4321 static void
4322 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4323 {
4324 struct scroll_bar *bar = client_data;
4325 XmScrollBarCallbackStruct *cs = call_data;
4326 int part = -1, whole = 0, portion = 0;
4327
4328 switch (cs->reason)
4329 {
4330 case XmCR_DECREMENT:
4331 bar->dragging = Qnil;
4332 part = scroll_bar_up_arrow;
4333 break;
4334
4335 case XmCR_INCREMENT:
4336 bar->dragging = Qnil;
4337 part = scroll_bar_down_arrow;
4338 break;
4339
4340 case XmCR_PAGE_DECREMENT:
4341 bar->dragging = Qnil;
4342 part = scroll_bar_above_handle;
4343 break;
4344
4345 case XmCR_PAGE_INCREMENT:
4346 bar->dragging = Qnil;
4347 part = scroll_bar_below_handle;
4348 break;
4349
4350 case XmCR_TO_TOP:
4351 bar->dragging = Qnil;
4352 part = scroll_bar_to_top;
4353 break;
4354
4355 case XmCR_TO_BOTTOM:
4356 bar->dragging = Qnil;
4357 part = scroll_bar_to_bottom;
4358 break;
4359
4360 case XmCR_DRAG:
4361 {
4362 int slider_size;
4363
4364 /* Get the slider size. */
4365 block_input ();
4366 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4367 unblock_input ();
4368
4369 whole = XM_SB_MAX - slider_size;
4370 portion = min (cs->value, whole);
4371 part = scroll_bar_handle;
4372 bar->dragging = make_number (cs->value);
4373 }
4374 break;
4375
4376 case XmCR_VALUE_CHANGED:
4377 break;
4378 };
4379
4380 if (part >= 0)
4381 {
4382 window_being_scrolled = bar->window;
4383 last_scroll_bar_part = part;
4384 x_send_scroll_bar_event (bar->window, part, portion, whole);
4385 }
4386 }
4387
4388 #elif defined USE_GTK
4389
4390 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4391 bar widget. DATA is a pointer to the scroll_bar structure. */
4392
4393 static gboolean
4394 xg_scroll_callback (GtkRange *range,
4395 GtkScrollType scroll,
4396 gdouble value,
4397 gpointer user_data)
4398 {
4399 struct scroll_bar *bar = user_data;
4400 gdouble position;
4401 int part = -1, whole = 0, portion = 0;
4402 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
4403 struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
4404
4405 if (xg_ignore_gtk_scrollbar) return FALSE;
4406 position = gtk_adjustment_get_value (adj);
4407
4408
4409 switch (scroll)
4410 {
4411 case GTK_SCROLL_JUMP:
4412 /* Buttons 1 2 or 3 must be grabbed. */
4413 if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0
4414 && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4))
4415 {
4416 part = scroll_bar_handle;
4417 whole = gtk_adjustment_get_upper (adj) -
4418 gtk_adjustment_get_page_size (adj);
4419 portion = min ((int)position, whole);
4420 bar->dragging = make_number ((int)portion);
4421 }
4422 break;
4423 case GTK_SCROLL_STEP_BACKWARD:
4424 part = scroll_bar_up_arrow;
4425 bar->dragging = Qnil;
4426 break;
4427 case GTK_SCROLL_STEP_FORWARD:
4428 part = scroll_bar_down_arrow;
4429 bar->dragging = Qnil;
4430 break;
4431 case GTK_SCROLL_PAGE_BACKWARD:
4432 part = scroll_bar_above_handle;
4433 bar->dragging = Qnil;
4434 break;
4435 case GTK_SCROLL_PAGE_FORWARD:
4436 part = scroll_bar_below_handle;
4437 bar->dragging = Qnil;
4438 break;
4439 }
4440
4441 if (part >= 0)
4442 {
4443 window_being_scrolled = bar->window;
4444 last_scroll_bar_part = part;
4445 x_send_scroll_bar_event (bar->window, part, portion, whole);
4446 }
4447
4448 return FALSE;
4449 }
4450
4451 /* Callback for button release. Sets dragging to Qnil when dragging is done. */
4452
4453 static gboolean
4454 xg_end_scroll_callback (GtkWidget *widget,
4455 GdkEventButton *event,
4456 gpointer user_data)
4457 {
4458 struct scroll_bar *bar = user_data;
4459 bar->dragging = Qnil;
4460 if (WINDOWP (window_being_scrolled))
4461 {
4462 x_send_scroll_bar_event (window_being_scrolled,
4463 scroll_bar_end_scroll, 0, 0);
4464 window_being_scrolled = Qnil;
4465 }
4466
4467 return FALSE;
4468 }
4469
4470
4471 #else /* not USE_GTK and not USE_MOTIF */
4472
4473 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4474 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4475 scroll bar struct. CALL_DATA is a pointer to a float saying where
4476 the thumb is. */
4477
4478 static void
4479 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4480 {
4481 struct scroll_bar *bar = client_data;
4482 float *top_addr = call_data;
4483 float top = *top_addr;
4484 float shown;
4485 int whole, portion, height;
4486 int part;
4487
4488 /* Get the size of the thumb, a value between 0 and 1. */
4489 block_input ();
4490 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4491 unblock_input ();
4492
4493 whole = 10000000;
4494 portion = shown < 1 ? top * whole : 0;
4495
4496 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
4497 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4498 the bottom, so we force the scrolling whenever we see that we're
4499 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4500 we try to ensure that we always stay two pixels away from the
4501 bottom). */
4502 part = scroll_bar_down_arrow;
4503 else
4504 part = scroll_bar_handle;
4505
4506 window_being_scrolled = bar->window;
4507 bar->dragging = make_number (portion);
4508 last_scroll_bar_part = part;
4509 x_send_scroll_bar_event (bar->window, part, portion, whole);
4510 }
4511
4512
4513 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4514 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4515 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4516 the scroll bar. CALL_DATA is an integer specifying the action that
4517 has taken place. Its magnitude is in the range 0..height of the
4518 scroll bar. Negative values mean scroll towards buffer start.
4519 Values < height of scroll bar mean line-wise movement. */
4520
4521 static void
4522 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4523 {
4524 struct scroll_bar *bar = client_data;
4525 /* The position really is stored cast to a pointer. */
4526 int position = (intptr_t) call_data;
4527 Dimension height;
4528 int part;
4529
4530 /* Get the height of the scroll bar. */
4531 block_input ();
4532 XtVaGetValues (widget, XtNheight, &height, NULL);
4533 unblock_input ();
4534
4535 if (eabs (position) >= height)
4536 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
4537
4538 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
4539 it maps line-movement to call_data = max(5, height/20). */
4540 else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
4541 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
4542 else
4543 part = scroll_bar_move_ratio;
4544
4545 window_being_scrolled = bar->window;
4546 bar->dragging = Qnil;
4547 last_scroll_bar_part = part;
4548 x_send_scroll_bar_event (bar->window, part, position, height);
4549 }
4550
4551 #endif /* not USE_GTK and not USE_MOTIF */
4552
4553 #define SCROLL_BAR_NAME "verticalScrollBar"
4554
4555 /* Create the widget for scroll bar BAR on frame F. Record the widget
4556 and X window of the scroll bar in BAR. */
4557
4558 #ifdef USE_GTK
4559 static void
4560 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4561 {
4562 const char *scroll_bar_name = SCROLL_BAR_NAME;
4563
4564 block_input ();
4565 xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4566 G_CALLBACK (xg_end_scroll_callback),
4567 scroll_bar_name);
4568 unblock_input ();
4569 }
4570
4571 #else /* not USE_GTK */
4572
4573 static void
4574 x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4575 {
4576 Window xwindow;
4577 Widget widget;
4578 Arg av[20];
4579 int ac = 0;
4580 const char *scroll_bar_name = SCROLL_BAR_NAME;
4581 unsigned long pixel;
4582
4583 block_input ();
4584
4585 #ifdef USE_MOTIF
4586 /* Set resources. Create the widget. */
4587 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4588 XtSetArg (av[ac], XmNminimum, 0); ++ac;
4589 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
4590 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
4591 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
4592 XtSetArg (av[ac], XmNincrement, 1); ++ac;
4593 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
4594
4595 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4596 if (pixel != -1)
4597 {
4598 XtSetArg (av[ac], XmNforeground, pixel);
4599 ++ac;
4600 }
4601
4602 pixel = f->output_data.x->scroll_bar_background_pixel;
4603 if (pixel != -1)
4604 {
4605 XtSetArg (av[ac], XmNbackground, pixel);
4606 ++ac;
4607 }
4608
4609 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
4610 (char *) scroll_bar_name, av, ac);
4611
4612 /* Add one callback for everything that can happen. */
4613 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
4614 (XtPointer) bar);
4615 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
4616 (XtPointer) bar);
4617 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
4618 (XtPointer) bar);
4619 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
4620 (XtPointer) bar);
4621 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
4622 (XtPointer) bar);
4623 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
4624 (XtPointer) bar);
4625 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
4626 (XtPointer) bar);
4627
4628 /* Realize the widget. Only after that is the X window created. */
4629 XtRealizeWidget (widget);
4630
4631 /* Set the cursor to an arrow. I didn't find a resource to do that.
4632 And I'm wondering why it hasn't an arrow cursor by default. */
4633 XDefineCursor (XtDisplay (widget), XtWindow (widget),
4634 f->output_data.x->nontext_cursor);
4635
4636 #else /* !USE_MOTIF i.e. use Xaw */
4637
4638 /* Set resources. Create the widget. The background of the
4639 Xaw3d scroll bar widget is a little bit light for my taste.
4640 We don't alter it here to let users change it according
4641 to their taste with `emacs*verticalScrollBar.background: xxx'. */
4642 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4643 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
4644 /* For smoother scrolling with Xaw3d -sm */
4645 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4646
4647 pixel = f->output_data.x->scroll_bar_foreground_pixel;
4648 if (pixel != -1)
4649 {
4650 XtSetArg (av[ac], XtNforeground, pixel);
4651 ++ac;
4652 }
4653
4654 pixel = f->output_data.x->scroll_bar_background_pixel;
4655 if (pixel != -1)
4656 {
4657 XtSetArg (av[ac], XtNbackground, pixel);
4658 ++ac;
4659 }
4660
4661 /* Top/bottom shadow colors. */
4662
4663 /* Allocate them, if necessary. */
4664 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
4665 {
4666 pixel = f->output_data.x->scroll_bar_background_pixel;
4667 if (pixel != -1)
4668 {
4669 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4670 FRAME_X_COLORMAP (f),
4671 &pixel, 1.2, 0x8000))
4672 pixel = -1;
4673 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
4674 }
4675 }
4676 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4677 {
4678 pixel = f->output_data.x->scroll_bar_background_pixel;
4679 if (pixel != -1)
4680 {
4681 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
4682 FRAME_X_COLORMAP (f),
4683 &pixel, 0.6, 0x4000))
4684 pixel = -1;
4685 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
4686 }
4687 }
4688
4689 #ifdef XtNbeNiceToColormap
4690 /* Tell the toolkit about them. */
4691 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
4692 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
4693 /* We tried to allocate a color for the top/bottom shadow, and
4694 failed, so tell Xaw3d to use dithering instead. */
4695 /* But only if we have a small colormap. Xaw3d can allocate nice
4696 colors itself. */
4697 {
4698 XtSetArg (av[ac], XtNbeNiceToColormap,
4699 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
4700 ++ac;
4701 }
4702 else
4703 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
4704 be more consistent with other emacs 3d colors, and since Xaw3d is
4705 not good at dealing with allocation failure. */
4706 {
4707 /* This tells Xaw3d to use real colors instead of dithering for
4708 the shadows. */
4709 XtSetArg (av[ac], XtNbeNiceToColormap, False);
4710 ++ac;
4711
4712 /* Specify the colors. */
4713 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
4714 if (pixel != -1)
4715 {
4716 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
4717 ++ac;
4718 }
4719 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
4720 if (pixel != -1)
4721 {
4722 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
4723 ++ac;
4724 }
4725 }
4726 #endif
4727
4728 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
4729 f->output_data.x->edit_widget, av, ac);
4730
4731 {
4732 char const *initial = "";
4733 char const *val = initial;
4734 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
4735 #ifdef XtNarrowScrollbars
4736 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
4737 #endif
4738 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
4739 if (xaw3d_arrow_scroll || val == initial)
4740 { /* ARROW_SCROLL */
4741 xaw3d_arrow_scroll = True;
4742 /* Isn't that just a personal preference ? --Stef */
4743 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
4744 }
4745 }
4746
4747 /* Define callbacks. */
4748 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
4749 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
4750 (XtPointer) bar);
4751
4752 /* Realize the widget. Only after that is the X window created. */
4753 XtRealizeWidget (widget);
4754
4755 #endif /* !USE_MOTIF */
4756
4757 /* Install an action hook that lets us detect when the user
4758 finishes interacting with a scroll bar. */
4759 if (action_hook_id == 0)
4760 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
4761
4762 /* Remember X window and widget in the scroll bar vector. */
4763 SET_SCROLL_BAR_X_WIDGET (bar, widget);
4764 xwindow = XtWindow (widget);
4765 bar->x_window = xwindow;
4766
4767 unblock_input ();
4768 }
4769 #endif /* not USE_GTK */
4770
4771
4772 /* Set the thumb size and position of scroll bar BAR. We are currently
4773 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4774
4775 #ifdef USE_GTK
4776 static void
4777 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
4778 {
4779 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4780 }
4781
4782 #else /* not USE_GTK */
4783 static void
4784 x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
4785 int whole)
4786 {
4787 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4788 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4789 float top, shown;
4790
4791 block_input ();
4792
4793 #ifdef USE_MOTIF
4794
4795 if (scroll_bar_adjust_thumb_portion_p)
4796 {
4797 /* We use an estimate of 30 chars per line rather than the real
4798 `portion' value. This has the disadvantage that the thumb size
4799 is not very representative, but it makes our life a lot easier.
4800 Otherwise, we have to constantly adjust the thumb size, which
4801 we can't always do quickly enough: while dragging, the size of
4802 the thumb might prevent the user from dragging the thumb all the
4803 way to the end. but Motif and some versions of Xaw3d don't allow
4804 updating the thumb size while dragging. Also, even if we can update
4805 its size, the update will often happen too late.
4806 If you don't believe it, check out revision 1.650 of xterm.c to see
4807 what hoops we were going through and the still poor behavior we got. */
4808 portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
4809 /* When the thumb is at the bottom, position == whole.
4810 So we need to increase `whole' to make space for the thumb. */
4811 whole += portion;
4812 }
4813
4814 if (whole <= 0)
4815 top = 0, shown = 1;
4816 else
4817 {
4818 top = (float) position / whole;
4819 shown = (float) portion / whole;
4820 }
4821
4822 if (NILP (bar->dragging))
4823 {
4824 int size, value;
4825
4826 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
4827 is the scroll bar's maximum and MIN is the scroll bar's minimum
4828 value. */
4829 size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
4830
4831 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
4832 value = top * XM_SB_MAX;
4833 value = min (value, XM_SB_MAX - size);
4834
4835 XmScrollBarSetValues (widget, value, size, 0, 0, False);
4836 }
4837 #else /* !USE_MOTIF i.e. use Xaw */
4838
4839 if (whole == 0)
4840 top = 0, shown = 1;
4841 else
4842 {
4843 top = (float) position / whole;
4844 shown = (float) portion / whole;
4845 }
4846
4847 {
4848 float old_top, old_shown;
4849 Dimension height;
4850 XtVaGetValues (widget,
4851 XtNtopOfThumb, &old_top,
4852 XtNshown, &old_shown,
4853 XtNheight, &height,
4854 NULL);
4855
4856 /* Massage the top+shown values. */
4857 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
4858 top = max (0, min (1, top));
4859 else
4860 top = old_top;
4861 /* Keep two pixels available for moving the thumb down. */
4862 shown = max (0, min (1 - top - (2.0f / height), shown));
4863
4864 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
4865 check that your system's configuration file contains a define
4866 for `NARROWPROTO'. See s/freebsd.h for an example. */
4867 if (top != old_top || shown != old_shown)
4868 {
4869 if (NILP (bar->dragging))
4870 XawScrollbarSetThumb (widget, top, shown);
4871 else
4872 {
4873 /* Try to make the scrolling a tad smoother. */
4874 if (!xaw3d_pick_top)
4875 shown = min (shown, old_shown);
4876
4877 XawScrollbarSetThumb (widget, top, shown);
4878 }
4879 }
4880 }
4881 #endif /* !USE_MOTIF */
4882
4883 unblock_input ();
4884 }
4885 #endif /* not USE_GTK */
4886
4887 #endif /* USE_TOOLKIT_SCROLL_BARS */
4888
4889
4890 \f
4891 /************************************************************************
4892 Scroll bars, general
4893 ************************************************************************/
4894
4895 /* Create a scroll bar and return the scroll bar vector for it. W is
4896 the Emacs window on which to create the scroll bar. TOP, LEFT,
4897 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4898 scroll bar. */
4899
4900 static struct scroll_bar *
4901 x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
4902 {
4903 struct frame *f = XFRAME (w->frame);
4904 struct scroll_bar *bar
4905 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
4906 Lisp_Object barobj;
4907
4908 block_input ();
4909
4910 #ifdef USE_TOOLKIT_SCROLL_BARS
4911 x_create_toolkit_scroll_bar (f, bar);
4912 #else /* not USE_TOOLKIT_SCROLL_BARS */
4913 {
4914 XSetWindowAttributes a;
4915 unsigned long mask;
4916 Window window;
4917
4918 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
4919 if (a.background_pixel == -1)
4920 a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
4921
4922 a.event_mask = (ButtonPressMask | ButtonReleaseMask
4923 | ButtonMotionMask | PointerMotionHintMask
4924 | ExposureMask);
4925 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
4926
4927 mask = (CWBackPixel | CWEventMask | CWCursor);
4928
4929 /* Clear the area of W that will serve as a scroll bar. This is
4930 for the case that a window has been split horizontally. In
4931 this case, no clear_frame is generated to reduce flickering. */
4932 if (width > 0 && height > 0)
4933 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4934 left, top, width,
4935 window_box_height (w), False);
4936
4937 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4938 /* Position and size of scroll bar. */
4939 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4940 top,
4941 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4942 height,
4943 /* Border width, depth, class, and visual. */
4944 0,
4945 CopyFromParent,
4946 CopyFromParent,
4947 CopyFromParent,
4948 /* Attributes. */
4949 mask, &a);
4950 bar->x_window = window;
4951 }
4952 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4953
4954 XSETWINDOW (bar->window, w);
4955 bar->top = top;
4956 bar->left = left;
4957 bar->width = width;
4958 bar->height = height;
4959 bar->start = 0;
4960 bar->end = 0;
4961 bar->dragging = Qnil;
4962 bar->fringe_extended_p = 0;
4963
4964 /* Add bar to its frame's list of scroll bars. */
4965 bar->next = FRAME_SCROLL_BARS (f);
4966 bar->prev = Qnil;
4967 XSETVECTOR (barobj, bar);
4968 fset_scroll_bars (f, barobj);
4969 if (!NILP (bar->next))
4970 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4971
4972 /* Map the window/widget. */
4973 #ifdef USE_TOOLKIT_SCROLL_BARS
4974 {
4975 #ifdef USE_GTK
4976 xg_update_scrollbar_pos (f,
4977 bar->x_window,
4978 top,
4979 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4980 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4981 max (height, 1));
4982 #else /* not USE_GTK */
4983 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4984 XtConfigureWidget (scroll_bar,
4985 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4986 top,
4987 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4988 max (height, 1), 0);
4989 XtMapWidget (scroll_bar);
4990 #endif /* not USE_GTK */
4991 }
4992 #else /* not USE_TOOLKIT_SCROLL_BARS */
4993 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
4994 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4995
4996 unblock_input ();
4997 return bar;
4998 }
4999
5000
5001 #ifndef USE_TOOLKIT_SCROLL_BARS
5002
5003 /* Draw BAR's handle in the proper position.
5004
5005 If the handle is already drawn from START to END, don't bother
5006 redrawing it, unless REBUILD is non-zero; in that case, always
5007 redraw it. (REBUILD is handy for drawing the handle after expose
5008 events.)
5009
5010 Normally, we want to constrain the start and end of the handle to
5011 fit inside its rectangle, but if the user is dragging the scroll
5012 bar handle, we want to let them drag it down all the way, so that
5013 the bar's top is as far down as it goes; otherwise, there's no way
5014 to move to the very end of the buffer. */
5015
5016 static void
5017 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild)
5018 {
5019 int dragging = ! NILP (bar->dragging);
5020 Window w = bar->x_window;
5021 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5022 GC gc = f->output_data.x->normal_gc;
5023
5024 /* If the display is already accurate, do nothing. */
5025 if (! rebuild
5026 && start == bar->start
5027 && end == bar->end)
5028 return;
5029
5030 block_input ();
5031
5032 {
5033 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
5034 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
5035 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5036
5037 /* Make sure the values are reasonable, and try to preserve
5038 the distance between start and end. */
5039 {
5040 int length = end - start;
5041
5042 if (start < 0)
5043 start = 0;
5044 else if (start > top_range)
5045 start = top_range;
5046 end = start + length;
5047
5048 if (end < start)
5049 end = start;
5050 else if (end > top_range && ! dragging)
5051 end = top_range;
5052 }
5053
5054 /* Store the adjusted setting in the scroll bar. */
5055 bar->start = start;
5056 bar->end = end;
5057
5058 /* Clip the end position, just for display. */
5059 if (end > top_range)
5060 end = top_range;
5061
5062 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
5063 below top positions, to make sure the handle is always at least
5064 that many pixels tall. */
5065 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5066
5067 /* Draw the empty space above the handle. Note that we can't clear
5068 zero-height areas; that means "clear to end of window." */
5069 if (start > 0)
5070 x_clear_area (FRAME_X_DISPLAY (f), w,
5071 /* x, y, width, height, and exposures. */
5072 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5073 VERTICAL_SCROLL_BAR_TOP_BORDER,
5074 inside_width, start,
5075 False);
5076
5077 /* Change to proper foreground color if one is specified. */
5078 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5079 XSetForeground (FRAME_X_DISPLAY (f), gc,
5080 f->output_data.x->scroll_bar_foreground_pixel);
5081
5082 /* Draw the handle itself. */
5083 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
5084 /* x, y, width, height */
5085 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5086 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
5087 inside_width, end - start);
5088
5089 /* Restore the foreground color of the GC if we changed it above. */
5090 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5091 XSetForeground (FRAME_X_DISPLAY (f), gc,
5092 FRAME_FOREGROUND_PIXEL (f));
5093
5094 /* Draw the empty space below the handle. Note that we can't
5095 clear zero-height areas; that means "clear to end of window." */
5096 if (end < inside_height)
5097 x_clear_area (FRAME_X_DISPLAY (f), w,
5098 /* x, y, width, height, and exposures. */
5099 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5100 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
5101 inside_width, inside_height - end,
5102 False);
5103
5104 }
5105
5106 unblock_input ();
5107 }
5108
5109 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5110
5111 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5112 nil. */
5113
5114 static void
5115 x_scroll_bar_remove (struct scroll_bar *bar)
5116 {
5117 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5118 block_input ();
5119
5120 #ifdef USE_TOOLKIT_SCROLL_BARS
5121 #ifdef USE_GTK
5122 xg_remove_scroll_bar (f, bar->x_window);
5123 #else /* not USE_GTK */
5124 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
5125 #endif /* not USE_GTK */
5126 #else
5127 XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
5128 #endif
5129
5130 /* Dissociate this scroll bar from its window. */
5131 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
5132
5133 unblock_input ();
5134 }
5135
5136
5137 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5138 that we are displaying PORTION characters out of a total of WHOLE
5139 characters, starting at POSITION. If WINDOW has no scroll bar,
5140 create one. */
5141
5142 static void
5143 XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
5144 {
5145 struct frame *f = XFRAME (w->frame);
5146 Lisp_Object barobj;
5147 struct scroll_bar *bar;
5148 int top, height, left, sb_left, width, sb_width;
5149 int window_y, window_height;
5150 #ifdef USE_TOOLKIT_SCROLL_BARS
5151 bool fringe_extended_p;
5152 #endif
5153
5154 /* Get window dimensions. */
5155 window_box (w, -1, 0, &window_y, 0, &window_height);
5156 top = window_y;
5157 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5158 height = window_height;
5159
5160 /* Compute the left edge of the scroll bar area. */
5161 left = WINDOW_SCROLL_BAR_AREA_X (w);
5162
5163 /* Compute the width of the scroll bar which might be less than
5164 the width of the area reserved for the scroll bar. */
5165 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5166 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5167 else
5168 sb_width = width;
5169
5170 /* Compute the left edge of the scroll bar. */
5171 #ifdef USE_TOOLKIT_SCROLL_BARS
5172 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5173 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5174 else
5175 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5176 #else
5177 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5178 sb_left = left + width - sb_width;
5179 else
5180 sb_left = left;
5181 #endif
5182
5183 #ifdef USE_TOOLKIT_SCROLL_BARS
5184 fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
5185 #endif
5186
5187 /* Does the scroll bar exist yet? */
5188 if (NILP (w->vertical_scroll_bar))
5189 {
5190 if (width > 0 && height > 0)
5191 {
5192 block_input ();
5193 #ifdef USE_TOOLKIT_SCROLL_BARS
5194 if (fringe_extended_p)
5195 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5196 sb_left, top, sb_width, height, False);
5197 else
5198 #endif
5199 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5200 left, top, width, height, False);
5201 unblock_input ();
5202 }
5203
5204 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5205 }
5206 else
5207 {
5208 /* It may just need to be moved and resized. */
5209 unsigned int mask = 0;
5210
5211 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5212
5213 block_input ();
5214
5215 if (sb_left != bar->left)
5216 mask |= CWX;
5217 if (top != bar->top)
5218 mask |= CWY;
5219 if (sb_width != bar->width)
5220 mask |= CWWidth;
5221 if (height != bar->height)
5222 mask |= CWHeight;
5223
5224 #ifdef USE_TOOLKIT_SCROLL_BARS
5225
5226 /* Move/size the scroll bar widget. */
5227 if (mask || bar->fringe_extended_p != fringe_extended_p)
5228 {
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 {
5233 if (fringe_extended_p)
5234 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5235 sb_left, top, sb_width, height, False);
5236 else
5237 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5238 left, top, width, height, False);
5239 }
5240 #ifdef USE_GTK
5241 xg_update_scrollbar_pos (f,
5242 bar->x_window,
5243 top,
5244 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5245 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
5246 max (height, 1));
5247 #else /* not USE_GTK */
5248 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5249 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5250 top,
5251 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5252 max (height, 1), 0);
5253 #endif /* not USE_GTK */
5254 }
5255 #else /* not USE_TOOLKIT_SCROLL_BARS */
5256
5257 /* Clear areas not covered by the scroll bar because of
5258 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
5259 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
5260 {
5261 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5262 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5263 height, False);
5264 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5265 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5266 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5267 height, False);
5268 }
5269
5270 /* Clear areas not covered by the scroll bar because it's not as
5271 wide as the area reserved for it. This makes sure a
5272 previous mode line display is cleared after C-x 2 C-x 1, for
5273 example. */
5274 {
5275 int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5276 int rest = area_width - sb_width;
5277 if (rest > 0 && height > 0)
5278 {
5279 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5280 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5281 left + area_width - rest, top,
5282 rest, height, False);
5283 else
5284 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5285 left, top, rest, height, False);
5286 }
5287 }
5288
5289 /* Move/size the scroll bar window. */
5290 if (mask)
5291 {
5292 XWindowChanges wc;
5293
5294 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5295 wc.y = top;
5296 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
5297 wc.height = height;
5298 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
5299 mask, &wc);
5300 }
5301
5302 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5303
5304 /* Remember new settings. */
5305 bar->left = sb_left;
5306 bar->top = top;
5307 bar->width = sb_width;
5308 bar->height = height;
5309
5310 unblock_input ();
5311 }
5312
5313 #ifdef USE_TOOLKIT_SCROLL_BARS
5314 bar->fringe_extended_p = fringe_extended_p;
5315
5316 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5317 #else /* not USE_TOOLKIT_SCROLL_BARS */
5318 /* Set the scroll bar's current state, unless we're currently being
5319 dragged. */
5320 if (NILP (bar->dragging))
5321 {
5322 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5323
5324 if (whole == 0)
5325 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5326 else
5327 {
5328 int start = ((double) position * top_range) / whole;
5329 int end = ((double) (position + portion) * top_range) / whole;
5330 x_scroll_bar_set_handle (bar, start, end, 0);
5331 }
5332 }
5333 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5334
5335 XSETVECTOR (barobj, bar);
5336 wset_vertical_scroll_bar (w, barobj);
5337 }
5338
5339
5340 /* The following three hooks are used when we're doing a thorough
5341 redisplay of the frame. We don't explicitly know which scroll bars
5342 are going to be deleted, because keeping track of when windows go
5343 away is a real pain - "Can you say set-window-configuration, boys
5344 and girls?" Instead, we just assert at the beginning of redisplay
5345 that *all* scroll bars are to be removed, and then save a scroll bar
5346 from the fiery pit when we actually redisplay its window. */
5347
5348 /* Arrange for all scroll bars on FRAME to be removed at the next call
5349 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5350 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5351
5352 static void
5353 XTcondemn_scroll_bars (struct frame *frame)
5354 {
5355 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5356 while (! NILP (FRAME_SCROLL_BARS (frame)))
5357 {
5358 Lisp_Object bar;
5359 bar = FRAME_SCROLL_BARS (frame);
5360 fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
5361 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5362 XSCROLL_BAR (bar)->prev = Qnil;
5363 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5364 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5365 fset_condemned_scroll_bars (frame, bar);
5366 }
5367 }
5368
5369
5370 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5371 Note that WINDOW isn't necessarily condemned at all. */
5372
5373 static void
5374 XTredeem_scroll_bar (struct window *window)
5375 {
5376 struct scroll_bar *bar;
5377 struct frame *f;
5378 Lisp_Object barobj;
5379
5380 /* We can't redeem this window's scroll bar if it doesn't have one. */
5381 if (NILP (window->vertical_scroll_bar))
5382 emacs_abort ();
5383
5384 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5385
5386 /* Unlink it from the condemned list. */
5387 f = XFRAME (WINDOW_FRAME (window));
5388 if (NILP (bar->prev))
5389 {
5390 /* If the prev pointer is nil, it must be the first in one of
5391 the lists. */
5392 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5393 /* It's not condemned. Everything's fine. */
5394 return;
5395 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5396 window->vertical_scroll_bar))
5397 fset_condemned_scroll_bars (f, bar->next);
5398 else
5399 /* If its prev pointer is nil, it must be at the front of
5400 one or the other! */
5401 emacs_abort ();
5402 }
5403 else
5404 XSCROLL_BAR (bar->prev)->next = bar->next;
5405
5406 if (! NILP (bar->next))
5407 XSCROLL_BAR (bar->next)->prev = bar->prev;
5408
5409 bar->next = FRAME_SCROLL_BARS (f);
5410 bar->prev = Qnil;
5411 XSETVECTOR (barobj, bar);
5412 fset_scroll_bars (f, barobj);
5413 if (! NILP (bar->next))
5414 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5415 }
5416
5417 /* Remove all scroll bars on FRAME that haven't been saved since the
5418 last call to `*condemn_scroll_bars_hook'. */
5419
5420 static void
5421 XTjudge_scroll_bars (struct frame *f)
5422 {
5423 Lisp_Object bar, next;
5424
5425 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5426
5427 /* Clear out the condemned list now so we won't try to process any
5428 more events on the hapless scroll bars. */
5429 fset_condemned_scroll_bars (f, Qnil);
5430
5431 for (; ! NILP (bar); bar = next)
5432 {
5433 struct scroll_bar *b = XSCROLL_BAR (bar);
5434
5435 x_scroll_bar_remove (b);
5436
5437 next = b->next;
5438 b->next = b->prev = Qnil;
5439 }
5440
5441 /* Now there should be no references to the condemned scroll bars,
5442 and they should get garbage-collected. */
5443 }
5444
5445
5446 #ifndef USE_TOOLKIT_SCROLL_BARS
5447 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
5448 is a no-op when using toolkit scroll bars.
5449
5450 This may be called from a signal handler, so we have to ignore GC
5451 mark bits. */
5452
5453 static void
5454 x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
5455 {
5456 Window w = bar->x_window;
5457 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5458 GC gc = f->output_data.x->normal_gc;
5459 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5460
5461 block_input ();
5462
5463 x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
5464
5465 /* Switch to scroll bar foreground color. */
5466 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5467 XSetForeground (FRAME_X_DISPLAY (f), gc,
5468 f->output_data.x->scroll_bar_foreground_pixel);
5469
5470 /* Draw a one-pixel border just inside the edges of the scroll bar. */
5471 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
5472
5473 /* x, y, width, height */
5474 0, 0,
5475 bar->width - 1 - width_trim - width_trim,
5476 bar->height - 1);
5477
5478 /* Restore the foreground color of the GC if we changed it above. */
5479 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
5480 XSetForeground (FRAME_X_DISPLAY (f), gc,
5481 FRAME_FOREGROUND_PIXEL (f));
5482
5483 unblock_input ();
5484
5485 }
5486 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5487
5488 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5489 is set to something other than NO_EVENT, it is enqueued.
5490
5491 This may be called from a signal handler, so we have to ignore GC
5492 mark bits. */
5493
5494
5495 static void
5496 x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
5497 {
5498 if (! WINDOWP (bar->window))
5499 emacs_abort ();
5500
5501 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5502 emacs_event->code = event->xbutton.button - Button1;
5503 emacs_event->modifiers
5504 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5505 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
5506 event->xbutton.state)
5507 | (event->type == ButtonRelease
5508 ? up_modifier
5509 : down_modifier));
5510 emacs_event->frame_or_window = bar->window;
5511 emacs_event->arg = Qnil;
5512 emacs_event->timestamp = event->xbutton.time;
5513 {
5514 int top_range
5515 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5516 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
5517
5518 if (y < 0) y = 0;
5519 if (y > top_range) y = top_range;
5520
5521 if (y < bar->start)
5522 emacs_event->part = scroll_bar_above_handle;
5523 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5524 emacs_event->part = scroll_bar_handle;
5525 else
5526 emacs_event->part = scroll_bar_below_handle;
5527
5528 #ifndef USE_TOOLKIT_SCROLL_BARS
5529 /* If the user has released the handle, set it to its final position. */
5530 if (event->type == ButtonRelease
5531 && ! NILP (bar->dragging))
5532 {
5533 int new_start = y - XINT (bar->dragging);
5534 int new_end = new_start + bar->end - bar->start;
5535
5536 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5537 bar->dragging = Qnil;
5538 }
5539 #endif
5540
5541 XSETINT (emacs_event->x, y);
5542 XSETINT (emacs_event->y, top_range);
5543 }
5544 }
5545
5546 #ifndef USE_TOOLKIT_SCROLL_BARS
5547
5548 /* Handle some mouse motion while someone is dragging the scroll bar.
5549
5550 This may be called from a signal handler, so we have to ignore GC
5551 mark bits. */
5552
5553 static void
5554 x_scroll_bar_note_movement (struct scroll_bar *bar, XEvent *event)
5555 {
5556 struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
5557
5558 last_mouse_movement_time = event->xmotion.time;
5559
5560 f->mouse_moved = 1;
5561 XSETVECTOR (last_mouse_scroll_bar, bar);
5562
5563 /* If we're dragging the bar, display it. */
5564 if (! NILP (bar->dragging))
5565 {
5566 /* Where should the handle be now? */
5567 int new_start = event->xmotion.y - XINT (bar->dragging);
5568
5569 if (new_start != bar->start)
5570 {
5571 int new_end = new_start + bar->end - bar->start;
5572
5573 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5574 }
5575 }
5576 }
5577
5578 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5579
5580 /* Return information to the user about the current position of the mouse
5581 on the scroll bar. */
5582
5583 static void
5584 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
5585 enum scroll_bar_part *part, Lisp_Object *x,
5586 Lisp_Object *y, Time *timestamp)
5587 {
5588 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5589 Window w = bar->x_window;
5590 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5591 int win_x, win_y;
5592 Window dummy_window;
5593 int dummy_coord;
5594 unsigned int dummy_mask;
5595
5596 block_input ();
5597
5598 /* Get the mouse's position relative to the scroll bar window, and
5599 report that. */
5600 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
5601
5602 /* Root, child, root x and root y. */
5603 &dummy_window, &dummy_window,
5604 &dummy_coord, &dummy_coord,
5605
5606 /* Position relative to scroll bar. */
5607 &win_x, &win_y,
5608
5609 /* Mouse buttons and modifier keys. */
5610 &dummy_mask))
5611 ;
5612 else
5613 {
5614 int top_range
5615 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
5616
5617 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5618
5619 if (! NILP (bar->dragging))
5620 win_y -= XINT (bar->dragging);
5621
5622 if (win_y < 0)
5623 win_y = 0;
5624 if (win_y > top_range)
5625 win_y = top_range;
5626
5627 *fp = f;
5628 *bar_window = bar->window;
5629
5630 if (! NILP (bar->dragging))
5631 *part = scroll_bar_handle;
5632 else if (win_y < bar->start)
5633 *part = scroll_bar_above_handle;
5634 else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5635 *part = scroll_bar_handle;
5636 else
5637 *part = scroll_bar_below_handle;
5638
5639 XSETINT (*x, win_y);
5640 XSETINT (*y, top_range);
5641
5642 f->mouse_moved = 0;
5643 last_mouse_scroll_bar = Qnil;
5644 }
5645
5646 *timestamp = last_mouse_movement_time;
5647
5648 unblock_input ();
5649 }
5650
5651
5652 /* The screen has been cleared so we may have changed foreground or
5653 background colors, and the scroll bars may need to be redrawn.
5654 Clear out the scroll bars, and ask for expose events, so we can
5655 redraw them. */
5656
5657 static void
5658 x_scroll_bar_clear (struct frame *f)
5659 {
5660 #ifndef USE_TOOLKIT_SCROLL_BARS
5661 Lisp_Object bar;
5662
5663 /* We can have scroll bars even if this is 0,
5664 if we just turned off scroll bar mode.
5665 But in that case we should not clear them. */
5666 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5667 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5668 bar = XSCROLL_BAR (bar)->next)
5669 XClearArea (FRAME_X_DISPLAY (f),
5670 XSCROLL_BAR (bar)->x_window,
5671 0, 0, 0, 0, True);
5672 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5673 }
5674
5675 \f
5676 /* The main X event-reading loop - XTread_socket. */
5677
5678 /* This holds the state XLookupString needs to implement dead keys
5679 and other tricks known as "compose processing". _X Window System_
5680 says that a portable program can't use this, but Stephen Gildea assures
5681 me that letting the compiler initialize it to zeros will work okay.
5682
5683 This must be defined outside of XTread_socket, for the same reasons
5684 given for enter_timestamp, above. */
5685
5686 static XComposeStatus compose_status;
5687
5688 /* Record the last 100 characters stored
5689 to help debug the loss-of-chars-during-GC problem. */
5690
5691 static int temp_index;
5692 static short temp_buffer[100];
5693
5694 #define STORE_KEYSYM_FOR_DEBUG(keysym) \
5695 if (temp_index == sizeof temp_buffer / sizeof (short)) \
5696 temp_index = 0; \
5697 temp_buffer[temp_index++] = (keysym)
5698
5699 /* Set this to nonzero to fake an "X I/O error"
5700 on a particular display. */
5701
5702 static struct x_display_info *XTread_socket_fake_io_error;
5703
5704 /* When we find no input here, we occasionally do a no-op command
5705 to verify that the X server is still running and we can still talk with it.
5706 We try all the open displays, one by one.
5707 This variable is used for cycling thru the displays. */
5708
5709 static struct x_display_info *next_noop_dpyinfo;
5710
5711 #if defined USE_X_TOOLKIT || defined USE_GTK
5712 #define SET_SAVED_BUTTON_EVENT \
5713 do \
5714 { \
5715 if (f->output_data.x->saved_menu_event == 0) \
5716 f->output_data.x->saved_menu_event = \
5717 xmalloc (sizeof (XEvent)); \
5718 *f->output_data.x->saved_menu_event = event; \
5719 inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
5720 XSETFRAME (inev.ie.frame_or_window, f); \
5721 } \
5722 while (0)
5723 #endif
5724
5725 enum
5726 {
5727 X_EVENT_NORMAL,
5728 X_EVENT_GOTO_OUT,
5729 X_EVENT_DROP
5730 };
5731
5732 /* Filter events for the current X input method.
5733 DPYINFO is the display this event is for.
5734 EVENT is the X event to filter.
5735
5736 Returns non-zero if the event was filtered, caller shall not process
5737 this event further.
5738 Returns zero if event is wasn't filtered. */
5739
5740 #ifdef HAVE_X_I18N
5741 static int
5742 x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
5743 {
5744 /* XFilterEvent returns non-zero if the input method has
5745 consumed the event. We pass the frame's X window to
5746 XFilterEvent because that's the one for which the IC
5747 was created. */
5748
5749 struct frame *f1 = x_any_window_to_frame (dpyinfo,
5750 event->xclient.window);
5751
5752 return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
5753 }
5754 #endif
5755
5756 #ifdef USE_GTK
5757 static int current_count;
5758 static int current_finish;
5759 static struct input_event *current_hold_quit;
5760
5761 /* This is the filter function invoked by the GTK event loop.
5762 It is invoked before the XEvent is translated to a GdkEvent,
5763 so we have a chance to act on the event before GTK. */
5764 static GdkFilterReturn
5765 event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
5766 {
5767 XEvent *xev = (XEvent *) gxev;
5768
5769 block_input ();
5770 if (current_count >= 0)
5771 {
5772 struct x_display_info *dpyinfo;
5773
5774 dpyinfo = x_display_info_for_display (xev->xany.display);
5775
5776 #ifdef HAVE_X_I18N
5777 /* Filter events for the current X input method.
5778 GTK calls XFilterEvent but not for key press and release,
5779 so we do it here. */
5780 if ((xev->type == KeyPress || xev->type == KeyRelease)
5781 && dpyinfo
5782 && x_filter_event (dpyinfo, xev))
5783 {
5784 unblock_input ();
5785 return GDK_FILTER_REMOVE;
5786 }
5787 #endif
5788
5789 if (! dpyinfo)
5790 current_finish = X_EVENT_NORMAL;
5791 else
5792 current_count +=
5793 handle_one_xevent (dpyinfo, xev, &current_finish,
5794 current_hold_quit);
5795 }
5796 else
5797 current_finish = x_dispatch_event (xev, xev->xany.display);
5798
5799 unblock_input ();
5800
5801 if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
5802 return GDK_FILTER_REMOVE;
5803
5804 return GDK_FILTER_CONTINUE;
5805 }
5806 #endif /* USE_GTK */
5807
5808
5809 static void xembed_send_message (struct frame *f, Time,
5810 enum xembed_message,
5811 long detail, long data1, long data2);
5812
5813 /* Handles the XEvent EVENT on display DPYINFO.
5814
5815 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5816 *FINISH is zero if caller should continue reading events.
5817 *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
5818
5819 We return the number of characters stored into the buffer. */
5820
5821 static int
5822 handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
5823 int *finish, struct input_event *hold_quit)
5824 {
5825 union {
5826 struct input_event ie;
5827 struct selection_input_event sie;
5828 } inev;
5829 int count = 0;
5830 int do_help = 0;
5831 ptrdiff_t nbytes = 0;
5832 struct frame *f = NULL;
5833 struct coding_system coding;
5834 XEvent event = *eventptr;
5835 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
5836 USE_SAFE_ALLOCA;
5837
5838 *finish = X_EVENT_NORMAL;
5839
5840 EVENT_INIT (inev.ie);
5841 inev.ie.kind = NO_EVENT;
5842 inev.ie.arg = Qnil;
5843
5844 if (pending_event_wait.eventtype == event.type)
5845 pending_event_wait.eventtype = 0; /* Indicates we got it. */
5846
5847 switch (event.type)
5848 {
5849 case ClientMessage:
5850 {
5851 if (event.xclient.message_type
5852 == dpyinfo->Xatom_wm_protocols
5853 && event.xclient.format == 32)
5854 {
5855 if (event.xclient.data.l[0]
5856 == dpyinfo->Xatom_wm_take_focus)
5857 {
5858 /* Use x_any_window_to_frame because this
5859 could be the shell widget window
5860 if the frame has no title bar. */
5861 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5862 #ifdef HAVE_X_I18N
5863 /* Not quite sure this is needed -pd */
5864 if (f && FRAME_XIC (f))
5865 XSetICFocus (FRAME_XIC (f));
5866 #endif
5867 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
5868 instructs the WM to set the input focus automatically for
5869 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
5870 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
5871 it has set the focus. So, XSetInputFocus below is not
5872 needed.
5873
5874 The call to XSetInputFocus below has also caused trouble. In
5875 cases where the XSetInputFocus done by the WM and the one
5876 below are temporally close (on a fast machine), the call
5877 below can generate additional FocusIn events which confuse
5878 Emacs. */
5879
5880 /* Since we set WM_TAKE_FOCUS, we must call
5881 XSetInputFocus explicitly. But not if f is null,
5882 since that might be an event for a deleted frame. */
5883 if (f)
5884 {
5885 Display *d = event.xclient.display;
5886 /* Catch and ignore errors, in case window has been
5887 iconified by a window manager such as GWM. */
5888 x_catch_errors (d);
5889 XSetInputFocus (d, event.xclient.window,
5890 /* The ICCCM says this is
5891 the only valid choice. */
5892 RevertToParent,
5893 event.xclient.data.l[1]);
5894 /* This is needed to detect the error
5895 if there is an error. */
5896 XSync (d, False);
5897 x_uncatch_errors ();
5898 }
5899 /* Not certain about handling scroll bars here */
5900 #endif /* 0 */
5901 goto done;
5902 }
5903
5904 if (event.xclient.data.l[0]
5905 == dpyinfo->Xatom_wm_save_yourself)
5906 {
5907 /* Save state modify the WM_COMMAND property to
5908 something which can reinstate us. This notifies
5909 the session manager, who's looking for such a
5910 PropertyNotify. Can restart processing when
5911 a keyboard or mouse event arrives. */
5912 /* If we have a session manager, don't set this.
5913 KDE will then start two Emacsen, one for the
5914 session manager and one for this. */
5915 #ifdef HAVE_X_SM
5916 if (! x_session_have_connection ())
5917 #endif
5918 {
5919 f = x_top_window_to_frame (dpyinfo,
5920 event.xclient.window);
5921 /* This is just so we only give real data once
5922 for a single Emacs process. */
5923 if (f == SELECTED_FRAME ())
5924 XSetCommand (FRAME_X_DISPLAY (f),
5925 event.xclient.window,
5926 initial_argv, initial_argc);
5927 else if (f)
5928 XSetCommand (FRAME_X_DISPLAY (f),
5929 event.xclient.window,
5930 0, 0);
5931 }
5932 goto done;
5933 }
5934
5935 if (event.xclient.data.l[0]
5936 == dpyinfo->Xatom_wm_delete_window)
5937 {
5938 f = x_any_window_to_frame (dpyinfo,
5939 event.xclient.window);
5940 if (!f)
5941 goto OTHER; /* May be a dialog that is to be removed */
5942
5943 inev.ie.kind = DELETE_WINDOW_EVENT;
5944 XSETFRAME (inev.ie.frame_or_window, f);
5945 goto done;
5946 }
5947
5948 goto done;
5949 }
5950
5951 if (event.xclient.message_type
5952 == dpyinfo->Xatom_wm_configure_denied)
5953 {
5954 goto done;
5955 }
5956
5957 if (event.xclient.message_type
5958 == dpyinfo->Xatom_wm_window_moved)
5959 {
5960 int new_x, new_y;
5961 f = x_window_to_frame (dpyinfo, event.xclient.window);
5962
5963 new_x = event.xclient.data.s[0];
5964 new_y = event.xclient.data.s[1];
5965
5966 if (f)
5967 {
5968 f->left_pos = new_x;
5969 f->top_pos = new_y;
5970 }
5971 goto done;
5972 }
5973
5974 #ifdef HACK_EDITRES
5975 if (event.xclient.message_type
5976 == dpyinfo->Xatom_editres)
5977 {
5978 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5979 if (f)
5980 _XEditResCheckMessages (f->output_data.x->widget, NULL,
5981 &event, NULL);
5982 goto done;
5983 }
5984 #endif /* HACK_EDITRES */
5985
5986 if ((event.xclient.message_type
5987 == dpyinfo->Xatom_DONE)
5988 || (event.xclient.message_type
5989 == dpyinfo->Xatom_PAGE))
5990 {
5991 /* Ghostview job completed. Kill it. We could
5992 reply with "Next" if we received "Page", but we
5993 currently never do because we are interested in
5994 images, only, which should have 1 page. */
5995 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
5996 f = x_window_to_frame (dpyinfo, event.xclient.window);
5997 if (!f)
5998 goto OTHER;
5999 x_kill_gs_process (pixmap, f);
6000 expose_frame (f, 0, 0, 0, 0);
6001 goto done;
6002 }
6003
6004 #ifdef USE_TOOLKIT_SCROLL_BARS
6005 /* Scroll bar callbacks send a ClientMessage from which
6006 we construct an input_event. */
6007 if (event.xclient.message_type
6008 == dpyinfo->Xatom_Scrollbar)
6009 {
6010 x_scroll_bar_to_input_event (&event, &inev.ie);
6011 *finish = X_EVENT_GOTO_OUT;
6012 goto done;
6013 }
6014 #endif /* USE_TOOLKIT_SCROLL_BARS */
6015
6016 /* XEmbed messages from the embedder (if any). */
6017 if (event.xclient.message_type
6018 == dpyinfo->Xatom_XEMBED)
6019 {
6020 enum xembed_message msg = event.xclient.data.l[1];
6021 if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
6022 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6023
6024 *finish = X_EVENT_GOTO_OUT;
6025 goto done;
6026 }
6027
6028 xft_settings_event (dpyinfo, &event);
6029
6030 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6031 if (!f)
6032 goto OTHER;
6033 if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
6034 *finish = X_EVENT_DROP;
6035 }
6036 break;
6037
6038 case SelectionNotify:
6039 last_user_time = event.xselection.time;
6040 #ifdef USE_X_TOOLKIT
6041 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
6042 goto OTHER;
6043 #endif /* not USE_X_TOOLKIT */
6044 x_handle_selection_notify (&event.xselection);
6045 break;
6046
6047 case SelectionClear: /* Someone has grabbed ownership. */
6048 last_user_time = event.xselectionclear.time;
6049 #ifdef USE_X_TOOLKIT
6050 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
6051 goto OTHER;
6052 #endif /* USE_X_TOOLKIT */
6053 {
6054 XSelectionClearEvent *eventp = &(event.xselectionclear);
6055
6056 inev.ie.kind = SELECTION_CLEAR_EVENT;
6057 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6058 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6059 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6060 }
6061 break;
6062
6063 case SelectionRequest: /* Someone wants our selection. */
6064 last_user_time = event.xselectionrequest.time;
6065 #ifdef USE_X_TOOLKIT
6066 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
6067 goto OTHER;
6068 #endif /* USE_X_TOOLKIT */
6069 {
6070 XSelectionRequestEvent *eventp = &(event.xselectionrequest);
6071
6072 inev.ie.kind = SELECTION_REQUEST_EVENT;
6073 SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
6074 SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
6075 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
6076 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
6077 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
6078 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
6079 }
6080 break;
6081
6082 case PropertyNotify:
6083 last_user_time = event.xproperty.time;
6084 f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
6085 if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
6086 if (x_handle_net_wm_state (f, &event.xproperty)
6087 && FRAME_ICONIFIED_P (f)
6088 && f->output_data.x->net_wm_state_hidden_seen)
6089 {
6090 /* Gnome shell does not iconify us when C-z is pressed.
6091 It hides the frame. So if our state says we aren't
6092 hidden anymore, treat it as deiconified. */
6093 SET_FRAME_VISIBLE (f, 1);
6094 SET_FRAME_ICONIFIED (f, 0);
6095 f->output_data.x->has_been_visible = 1;
6096 f->output_data.x->net_wm_state_hidden_seen = 0;
6097 inev.ie.kind = DEICONIFY_EVENT;
6098 XSETFRAME (inev.ie.frame_or_window, f);
6099 }
6100
6101 x_handle_property_notify (&event.xproperty);
6102 xft_settings_event (dpyinfo, &event);
6103 goto OTHER;
6104
6105 case ReparentNotify:
6106 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
6107 if (f)
6108 {
6109 int x, y;
6110 f->output_data.x->parent_desc = event.xreparent.parent;
6111 x_real_positions (f, &x, &y);
6112 f->left_pos = x;
6113 f->top_pos = y;
6114
6115 /* Perhaps reparented due to a WM restart. Reset this. */
6116 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
6117 FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
6118
6119 x_set_frame_alpha (f);
6120 }
6121 goto OTHER;
6122
6123 case Expose:
6124 f = x_window_to_frame (dpyinfo, event.xexpose.window);
6125 if (f)
6126 {
6127 #ifdef USE_GTK
6128 /* This seems to be needed for GTK 2.6. */
6129 x_clear_area (event.xexpose.display,
6130 event.xexpose.window,
6131 event.xexpose.x, event.xexpose.y,
6132 event.xexpose.width, event.xexpose.height,
6133 FALSE);
6134 #endif
6135 if (!FRAME_VISIBLE_P (f))
6136 {
6137 SET_FRAME_VISIBLE (f, 1);
6138 SET_FRAME_ICONIFIED (f, 0);
6139 f->output_data.x->has_been_visible = 1;
6140 SET_FRAME_GARBAGED (f);
6141 }
6142 else
6143 expose_frame (f,
6144 event.xexpose.x, event.xexpose.y,
6145 event.xexpose.width, event.xexpose.height);
6146 }
6147 else
6148 {
6149 #ifndef USE_TOOLKIT_SCROLL_BARS
6150 struct scroll_bar *bar;
6151 #endif
6152 #if defined USE_LUCID
6153 /* Submenus of the Lucid menu bar aren't widgets
6154 themselves, so there's no way to dispatch events
6155 to them. Recognize this case separately. */
6156 {
6157 Widget widget
6158 = x_window_to_menu_bar (event.xexpose.window);
6159 if (widget)
6160 xlwmenu_redisplay (widget);
6161 }
6162 #endif /* USE_LUCID */
6163
6164 #ifdef USE_TOOLKIT_SCROLL_BARS
6165 /* Dispatch event to the widget. */
6166 goto OTHER;
6167 #else /* not USE_TOOLKIT_SCROLL_BARS */
6168 bar = x_window_to_scroll_bar (event.xexpose.display,
6169 event.xexpose.window);
6170
6171 if (bar)
6172 x_scroll_bar_expose (bar, &event);
6173 #ifdef USE_X_TOOLKIT
6174 else
6175 goto OTHER;
6176 #endif /* USE_X_TOOLKIT */
6177 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6178 }
6179 break;
6180
6181 case GraphicsExpose: /* This occurs when an XCopyArea's
6182 source area was obscured or not
6183 available. */
6184 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
6185 if (f)
6186 {
6187 expose_frame (f,
6188 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
6189 event.xgraphicsexpose.width,
6190 event.xgraphicsexpose.height);
6191 }
6192 #ifdef USE_X_TOOLKIT
6193 else
6194 goto OTHER;
6195 #endif /* USE_X_TOOLKIT */
6196 break;
6197
6198 case NoExpose: /* This occurs when an XCopyArea's
6199 source area was completely
6200 available. */
6201 break;
6202
6203 case UnmapNotify:
6204 /* Redo the mouse-highlight after the tooltip has gone. */
6205 if (event.xmap.window == tip_window)
6206 {
6207 tip_window = 0;
6208 redo_mouse_highlight ();
6209 }
6210
6211 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
6212 if (f) /* F may no longer exist if
6213 the frame was deleted. */
6214 {
6215 bool visible = FRAME_VISIBLE_P (f);
6216 /* While a frame is unmapped, display generation is
6217 disabled; you don't want to spend time updating a
6218 display that won't ever be seen. */
6219 SET_FRAME_VISIBLE (f, 0);
6220 /* We can't distinguish, from the event, whether the window
6221 has become iconified or invisible. So assume, if it
6222 was previously visible, than now it is iconified.
6223 But x_make_frame_invisible clears both
6224 the visible flag and the iconified flag;
6225 and that way, we know the window is not iconified now. */
6226 if (visible || FRAME_ICONIFIED_P (f))
6227 {
6228 SET_FRAME_ICONIFIED (f, 1);
6229 inev.ie.kind = ICONIFY_EVENT;
6230 XSETFRAME (inev.ie.frame_or_window, f);
6231 }
6232 }
6233 goto OTHER;
6234
6235 case MapNotify:
6236 if (event.xmap.window == tip_window)
6237 /* The tooltip has been drawn already. Avoid
6238 the SET_FRAME_GARBAGED below. */
6239 goto OTHER;
6240
6241 /* We use x_top_window_to_frame because map events can
6242 come for sub-windows and they don't mean that the
6243 frame is visible. */
6244 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6245 if (f)
6246 {
6247 bool iconified = FRAME_ICONIFIED_P (f);
6248 /* wait_reading_process_output will notice this and update
6249 the frame's display structures.
6250 If we where iconified, we should not set garbaged,
6251 because that stops redrawing on Expose events. This looks
6252 bad if we are called from a recursive event loop
6253 (x_dispatch_event), for example when a dialog is up. */
6254 if (!iconified)
6255 SET_FRAME_GARBAGED (f);
6256
6257 /* Check if fullscreen was specified before we where mapped the
6258 first time, i.e. from the command line. */
6259 if (!f->output_data.x->has_been_visible)
6260 x_check_fullscreen (f);
6261
6262 SET_FRAME_VISIBLE (f, 1);
6263 SET_FRAME_ICONIFIED (f, 0);
6264 f->output_data.x->has_been_visible = 1;
6265
6266 if (iconified)
6267 {
6268 inev.ie.kind = DEICONIFY_EVENT;
6269 XSETFRAME (inev.ie.frame_or_window, f);
6270 }
6271 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6272 /* Force a redisplay sooner or later to update the
6273 frame titles in case this is the second frame. */
6274 record_asynch_buffer_change ();
6275
6276 #ifdef USE_GTK
6277 xg_frame_resized (f, -1, -1);
6278 #endif
6279 }
6280 goto OTHER;
6281
6282 case KeyPress:
6283
6284 last_user_time = event.xkey.time;
6285 ignore_next_mouse_click_timeout = 0;
6286
6287 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6288 /* Dispatch KeyPress events when in menu. */
6289 if (popup_activated ())
6290 goto OTHER;
6291 #endif
6292
6293 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
6294
6295 /* If mouse-highlight is an integer, input clears out
6296 mouse highlighting. */
6297 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
6298 && (f == 0
6299 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)))
6300 {
6301 clear_mouse_face (hlinfo);
6302 hlinfo->mouse_face_hidden = 1;
6303 }
6304
6305 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6306 if (f == 0)
6307 {
6308 /* Scroll bars consume key events, but we want
6309 the keys to go to the scroll bar's frame. */
6310 Widget widget = XtWindowToWidget (dpyinfo->display,
6311 event.xkey.window);
6312 if (widget && XmIsScrollBar (widget))
6313 {
6314 widget = XtParent (widget);
6315 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
6316 }
6317 }
6318 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6319
6320 if (f != 0)
6321 {
6322 KeySym keysym, orig_keysym;
6323 /* al%imercury@uunet.uu.net says that making this 81
6324 instead of 80 fixed a bug whereby meta chars made
6325 his Emacs hang.
6326
6327 It seems that some version of XmbLookupString has
6328 a bug of not returning XBufferOverflow in
6329 status_return even if the input is too long to
6330 fit in 81 bytes. So, we must prepare sufficient
6331 bytes for copy_buffer. 513 bytes (256 chars for
6332 two-byte character set) seems to be a fairly good
6333 approximation. -- 2000.8.10 handa@etl.go.jp */
6334 unsigned char copy_buffer[513];
6335 unsigned char *copy_bufptr = copy_buffer;
6336 int copy_bufsiz = sizeof (copy_buffer);
6337 int modifiers;
6338 Lisp_Object coding_system = Qlatin_1;
6339 Lisp_Object c;
6340
6341 #ifdef USE_GTK
6342 /* Don't pass keys to GTK. A Tab will shift focus to the
6343 tool bar in GTK 2.4. Keys will still go to menus and
6344 dialogs because in that case popup_activated is TRUE
6345 (see above). */
6346 *finish = X_EVENT_DROP;
6347 #endif
6348
6349 event.xkey.state
6350 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
6351 extra_keyboard_modifiers);
6352 modifiers = event.xkey.state;
6353
6354 /* This will have to go some day... */
6355
6356 /* make_lispy_event turns chars into control chars.
6357 Don't do it here because XLookupString is too eager. */
6358 event.xkey.state &= ~ControlMask;
6359 event.xkey.state &= ~(dpyinfo->meta_mod_mask
6360 | dpyinfo->super_mod_mask
6361 | dpyinfo->hyper_mod_mask
6362 | dpyinfo->alt_mod_mask);
6363
6364 /* In case Meta is ComposeCharacter,
6365 clear its status. According to Markus Ehrnsperger
6366 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6367 this enables ComposeCharacter to work whether or
6368 not it is combined with Meta. */
6369 if (modifiers & dpyinfo->meta_mod_mask)
6370 memset (&compose_status, 0, sizeof (compose_status));
6371
6372 #ifdef HAVE_X_I18N
6373 if (FRAME_XIC (f))
6374 {
6375 Status status_return;
6376
6377 coding_system = Vlocale_coding_system;
6378 nbytes = XmbLookupString (FRAME_XIC (f),
6379 &event.xkey, (char *) copy_bufptr,
6380 copy_bufsiz, &keysym,
6381 &status_return);
6382 if (status_return == XBufferOverflow)
6383 {
6384 copy_bufsiz = nbytes + 1;
6385 copy_bufptr = alloca (copy_bufsiz);
6386 nbytes = XmbLookupString (FRAME_XIC (f),
6387 &event.xkey, (char *) copy_bufptr,
6388 copy_bufsiz, &keysym,
6389 &status_return);
6390 }
6391 /* Xutf8LookupString is a new but already deprecated interface. -stef */
6392 if (status_return == XLookupNone)
6393 break;
6394 else if (status_return == XLookupChars)
6395 {
6396 keysym = NoSymbol;
6397 modifiers = 0;
6398 }
6399 else if (status_return != XLookupKeySym
6400 && status_return != XLookupBoth)
6401 emacs_abort ();
6402 }
6403 else
6404 nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
6405 copy_bufsiz, &keysym,
6406 &compose_status);
6407 #else
6408 nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
6409 copy_bufsiz, &keysym,
6410 &compose_status);
6411 #endif
6412
6413 /* If not using XIM/XIC, and a compose sequence is in progress,
6414 we break here. Otherwise, chars_matched is always 0. */
6415 if (compose_status.chars_matched > 0 && nbytes == 0)
6416 break;
6417
6418 memset (&compose_status, 0, sizeof (compose_status));
6419 orig_keysym = keysym;
6420
6421 /* Common for all keysym input events. */
6422 XSETFRAME (inev.ie.frame_or_window, f);
6423 inev.ie.modifiers
6424 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
6425 inev.ie.timestamp = event.xkey.time;
6426
6427 /* First deal with keysyms which have defined
6428 translations to characters. */
6429 if (keysym >= 32 && keysym < 128)
6430 /* Avoid explicitly decoding each ASCII character. */
6431 {
6432 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6433 inev.ie.code = keysym;
6434 goto done_keysym;
6435 }
6436
6437 /* Keysyms directly mapped to Unicode characters. */
6438 if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
6439 {
6440 if (keysym < 0x01000080)
6441 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
6442 else
6443 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
6444 inev.ie.code = keysym & 0xFFFFFF;
6445 goto done_keysym;
6446 }
6447
6448 /* Now non-ASCII. */
6449 if (HASH_TABLE_P (Vx_keysym_table)
6450 && (c = Fgethash (make_number (keysym),
6451 Vx_keysym_table,
6452 Qnil),
6453 NATNUMP (c)))
6454 {
6455 inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
6456 ? ASCII_KEYSTROKE_EVENT
6457 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6458 inev.ie.code = XFASTINT (c);
6459 goto done_keysym;
6460 }
6461
6462 /* Random non-modifier sorts of keysyms. */
6463 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
6464 || keysym == XK_Delete
6465 #ifdef XK_ISO_Left_Tab
6466 || (keysym >= XK_ISO_Left_Tab
6467 && keysym <= XK_ISO_Enter)
6468 #endif
6469 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
6470 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
6471 #ifdef HPUX
6472 /* This recognizes the "extended function
6473 keys". It seems there's no cleaner way.
6474 Test IsModifierKey to avoid handling
6475 mode_switch incorrectly. */
6476 || (XK_Select <= keysym && keysym < XK_KP_Space)
6477 #endif
6478 #ifdef XK_dead_circumflex
6479 || orig_keysym == XK_dead_circumflex
6480 #endif
6481 #ifdef XK_dead_grave
6482 || orig_keysym == XK_dead_grave
6483 #endif
6484 #ifdef XK_dead_tilde
6485 || orig_keysym == XK_dead_tilde
6486 #endif
6487 #ifdef XK_dead_diaeresis
6488 || orig_keysym == XK_dead_diaeresis
6489 #endif
6490 #ifdef XK_dead_macron
6491 || orig_keysym == XK_dead_macron
6492 #endif
6493 #ifdef XK_dead_degree
6494 || orig_keysym == XK_dead_degree
6495 #endif
6496 #ifdef XK_dead_acute
6497 || orig_keysym == XK_dead_acute
6498 #endif
6499 #ifdef XK_dead_cedilla
6500 || orig_keysym == XK_dead_cedilla
6501 #endif
6502 #ifdef XK_dead_breve
6503 || orig_keysym == XK_dead_breve
6504 #endif
6505 #ifdef XK_dead_ogonek
6506 || orig_keysym == XK_dead_ogonek
6507 #endif
6508 #ifdef XK_dead_caron
6509 || orig_keysym == XK_dead_caron
6510 #endif
6511 #ifdef XK_dead_doubleacute
6512 || orig_keysym == XK_dead_doubleacute
6513 #endif
6514 #ifdef XK_dead_abovedot
6515 || orig_keysym == XK_dead_abovedot
6516 #endif
6517 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
6518 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
6519 /* Any "vendor-specific" key is ok. */
6520 || (orig_keysym & (1 << 28))
6521 || (keysym != NoSymbol && nbytes == 0))
6522 && ! (IsModifierKey (orig_keysym)
6523 /* The symbols from XK_ISO_Lock
6524 to XK_ISO_Last_Group_Lock
6525 don't have real modifiers but
6526 should be treated similarly to
6527 Mode_switch by Emacs. */
6528 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6529 || (XK_ISO_Lock <= orig_keysym
6530 && orig_keysym <= XK_ISO_Last_Group_Lock)
6531 #endif
6532 ))
6533 {
6534 STORE_KEYSYM_FOR_DEBUG (keysym);
6535 /* make_lispy_event will convert this to a symbolic
6536 key. */
6537 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
6538 inev.ie.code = keysym;
6539 goto done_keysym;
6540 }
6541
6542 { /* Raw bytes, not keysym. */
6543 ptrdiff_t i;
6544 int nchars, len;
6545
6546 for (i = 0, nchars = 0; i < nbytes; i++)
6547 {
6548 if (ASCII_BYTE_P (copy_bufptr[i]))
6549 nchars++;
6550 STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
6551 }
6552
6553 if (nchars < nbytes)
6554 {
6555 /* Decode the input data. */
6556
6557 /* The input should be decoded with `coding_system'
6558 which depends on which X*LookupString function
6559 we used just above and the locale. */
6560 setup_coding_system (coding_system, &coding);
6561 coding.src_multibyte = 0;
6562 coding.dst_multibyte = 1;
6563 /* The input is converted to events, thus we can't
6564 handle composition. Anyway, there's no XIM that
6565 gives us composition information. */
6566 coding.common_flags &= ~CODING_ANNOTATION_MASK;
6567
6568 SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
6569 nbytes);
6570 coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
6571 coding.mode |= CODING_MODE_LAST_BLOCK;
6572 decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
6573 nbytes = coding.produced;
6574 nchars = coding.produced_char;
6575 copy_bufptr = coding.destination;
6576 }
6577
6578 /* Convert the input data to a sequence of
6579 character events. */
6580 for (i = 0; i < nbytes; i += len)
6581 {
6582 int ch;
6583 if (nchars == nbytes)
6584 ch = copy_bufptr[i], len = 1;
6585 else
6586 ch = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
6587 inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
6588 ? ASCII_KEYSTROKE_EVENT
6589 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6590 inev.ie.code = ch;
6591 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6592 }
6593
6594 count += nchars;
6595
6596 inev.ie.kind = NO_EVENT; /* Already stored above. */
6597
6598 if (keysym == NoSymbol)
6599 break;
6600 }
6601 }
6602 done_keysym:
6603 #ifdef HAVE_X_I18N
6604 /* Don't dispatch this event since XtDispatchEvent calls
6605 XFilterEvent, and two calls in a row may freeze the
6606 client. */
6607 break;
6608 #else
6609 goto OTHER;
6610 #endif
6611
6612 case KeyRelease:
6613 last_user_time = event.xkey.time;
6614 #ifdef HAVE_X_I18N
6615 /* Don't dispatch this event since XtDispatchEvent calls
6616 XFilterEvent, and two calls in a row may freeze the
6617 client. */
6618 break;
6619 #else
6620 goto OTHER;
6621 #endif
6622
6623 case EnterNotify:
6624 last_user_time = event.xcrossing.time;
6625 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6626
6627 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6628
6629 if (f && x_mouse_click_focus_ignore_position)
6630 ignore_next_mouse_click_timeout = event.xmotion.time + 200;
6631
6632 /* EnterNotify counts as mouse movement,
6633 so update things that depend on mouse position. */
6634 if (f && !f->output_data.x->hourglass_p)
6635 note_mouse_movement (f, &event.xmotion);
6636 #ifdef USE_GTK
6637 /* We may get an EnterNotify on the buttons in the toolbar. In that
6638 case we moved out of any highlighted area and need to note this. */
6639 if (!f && last_mouse_glyph_frame)
6640 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6641 #endif
6642 goto OTHER;
6643
6644 case FocusIn:
6645 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6646 goto OTHER;
6647
6648 case LeaveNotify:
6649 last_user_time = event.xcrossing.time;
6650 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6651
6652 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
6653 if (f)
6654 {
6655 if (f == hlinfo->mouse_face_mouse_frame)
6656 {
6657 /* If we move outside the frame, then we're
6658 certainly no longer on any text in the frame. */
6659 clear_mouse_face (hlinfo);
6660 hlinfo->mouse_face_mouse_frame = 0;
6661 }
6662
6663 /* Generate a nil HELP_EVENT to cancel a help-echo.
6664 Do it only if there's something to cancel.
6665 Otherwise, the startup message is cleared when
6666 the mouse leaves the frame. */
6667 if (any_help_event_p)
6668 do_help = -1;
6669 }
6670 #ifdef USE_GTK
6671 /* See comment in EnterNotify above */
6672 else if (last_mouse_glyph_frame)
6673 note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
6674 #endif
6675 goto OTHER;
6676
6677 case FocusOut:
6678 x_detect_focus_change (dpyinfo, &event, &inev.ie);
6679 goto OTHER;
6680
6681 case MotionNotify:
6682 {
6683 last_user_time = event.xmotion.time;
6684 previous_help_echo_string = help_echo_string;
6685 help_echo_string = Qnil;
6686
6687 if (dpyinfo->grabbed && last_mouse_frame
6688 && FRAME_LIVE_P (last_mouse_frame))
6689 f = last_mouse_frame;
6690 else
6691 f = x_window_to_frame (dpyinfo, event.xmotion.window);
6692
6693 if (hlinfo->mouse_face_hidden)
6694 {
6695 hlinfo->mouse_face_hidden = 0;
6696 clear_mouse_face (hlinfo);
6697 }
6698
6699 #ifdef USE_GTK
6700 if (f && xg_event_is_for_scrollbar (f, &event))
6701 f = 0;
6702 #endif
6703 if (f)
6704 {
6705
6706 /* Generate SELECT_WINDOW_EVENTs when needed.
6707 Don't let popup menus influence things (bug#1261). */
6708 if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
6709 {
6710 Lisp_Object window;
6711
6712 window = window_from_coordinates (f,
6713 event.xmotion.x, event.xmotion.y,
6714 0, 0);
6715
6716 /* Window will be selected only when it is not selected now and
6717 last mouse movement event was not in it. Minibuffer window
6718 will be selected only when it is active. */
6719 if (WINDOWP (window)
6720 && !EQ (window, last_window)
6721 && !EQ (window, selected_window)
6722 /* For click-to-focus window managers
6723 create event iff we don't leave the
6724 selected frame. */
6725 && (focus_follows_mouse
6726 || (EQ (XWINDOW (window)->frame,
6727 XWINDOW (selected_window)->frame))))
6728 {
6729 inev.ie.kind = SELECT_WINDOW_EVENT;
6730 inev.ie.frame_or_window = window;
6731 }
6732
6733 last_window=window;
6734 }
6735 if (!note_mouse_movement (f, &event.xmotion))
6736 help_echo_string = previous_help_echo_string;
6737 }
6738 else
6739 {
6740 #ifndef USE_TOOLKIT_SCROLL_BARS
6741 struct scroll_bar *bar
6742 = x_window_to_scroll_bar (event.xmotion.display,
6743 event.xmotion.window);
6744
6745 if (bar)
6746 x_scroll_bar_note_movement (bar, &event);
6747 #endif /* USE_TOOLKIT_SCROLL_BARS */
6748
6749 /* If we move outside the frame, then we're
6750 certainly no longer on any text in the frame. */
6751 clear_mouse_face (hlinfo);
6752 }
6753
6754 /* If the contents of the global variable help_echo_string
6755 has changed, generate a HELP_EVENT. */
6756 if (!NILP (help_echo_string)
6757 || !NILP (previous_help_echo_string))
6758 do_help = 1;
6759 goto OTHER;
6760 }
6761
6762 case ConfigureNotify:
6763 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
6764 #ifdef USE_GTK
6765 if (!f
6766 && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
6767 && event.xconfigure.window == FRAME_X_WINDOW (f))
6768 {
6769 xg_frame_resized (f, event.xconfigure.width,
6770 event.xconfigure.height);
6771 f = 0;
6772 }
6773 #endif
6774 if (f)
6775 {
6776 #ifndef USE_X_TOOLKIT
6777 #ifndef USE_GTK
6778 int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
6779 int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
6780
6781 /* In the toolkit version, change_frame_size
6782 is called by the code that handles resizing
6783 of the EmacsFrame widget. */
6784
6785 /* Even if the number of character rows and columns has
6786 not changed, the font size may have changed, so we need
6787 to check the pixel dimensions as well. */
6788 if (columns != FRAME_COLS (f)
6789 || rows != FRAME_LINES (f)
6790 || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
6791 || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
6792 {
6793 change_frame_size (f, rows, columns, 0, 1, 0);
6794 SET_FRAME_GARBAGED (f);
6795 cancel_mouse_face (f);
6796 }
6797
6798 FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
6799 FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
6800 #endif /* not USE_GTK */
6801 #endif
6802
6803 #ifdef USE_GTK
6804 /* GTK creates windows but doesn't map them.
6805 Only get real positions when mapped. */
6806 if (FRAME_GTK_OUTER_WIDGET (f)
6807 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
6808 #endif
6809 {
6810 x_real_positions (f, &f->left_pos, &f->top_pos);
6811 }
6812
6813 #ifdef HAVE_X_I18N
6814 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6815 xic_set_statusarea (f);
6816 #endif
6817
6818 }
6819 goto OTHER;
6820
6821 case ButtonRelease:
6822 case ButtonPress:
6823 {
6824 /* If we decide we want to generate an event to be seen
6825 by the rest of Emacs, we put it here. */
6826 bool tool_bar_p = 0;
6827
6828 memset (&compose_status, 0, sizeof (compose_status));
6829 last_mouse_glyph_frame = 0;
6830 last_user_time = event.xbutton.time;
6831
6832 if (dpyinfo->grabbed
6833 && last_mouse_frame
6834 && FRAME_LIVE_P (last_mouse_frame))
6835 f = last_mouse_frame;
6836 else
6837 f = x_window_to_frame (dpyinfo, event.xbutton.window);
6838
6839 #ifdef USE_GTK
6840 if (f && xg_event_is_for_scrollbar (f, &event))
6841 f = 0;
6842 #endif
6843 if (f)
6844 {
6845 /* Is this in the tool-bar? */
6846 if (WINDOWP (f->tool_bar_window)
6847 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
6848 {
6849 Lisp_Object window;
6850 int x = event.xbutton.x;
6851 int y = event.xbutton.y;
6852
6853 window = window_from_coordinates (f, x, y, 0, 1);
6854 tool_bar_p = EQ (window, f->tool_bar_window);
6855
6856 if (tool_bar_p && event.xbutton.button < 4)
6857 {
6858 handle_tool_bar_click (f, x, y,
6859 event.xbutton.type == ButtonPress,
6860 x_x_to_emacs_modifiers (dpyinfo,
6861 event.xbutton.state));
6862 }
6863 }
6864
6865 if (!tool_bar_p)
6866 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6867 if (! popup_activated ())
6868 #endif
6869 {
6870 if (ignore_next_mouse_click_timeout)
6871 {
6872 if (event.type == ButtonPress
6873 && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
6874 {
6875 ignore_next_mouse_click_timeout = 0;
6876 construct_mouse_click (&inev.ie, &event.xbutton, f);
6877 }
6878 if (event.type == ButtonRelease)
6879 ignore_next_mouse_click_timeout = 0;
6880 }
6881 else
6882 construct_mouse_click (&inev.ie, &event.xbutton, f);
6883 }
6884 if (FRAME_X_EMBEDDED_P (f))
6885 xembed_send_message (f, event.xbutton.time,
6886 XEMBED_REQUEST_FOCUS, 0, 0, 0);
6887 }
6888 else
6889 {
6890 struct scroll_bar *bar
6891 = x_window_to_scroll_bar (event.xbutton.display,
6892 event.xbutton.window);
6893
6894 #ifdef USE_TOOLKIT_SCROLL_BARS
6895 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6896 scroll bars. */
6897 if (bar && event.xbutton.state & ControlMask)
6898 {
6899 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6900 *finish = X_EVENT_DROP;
6901 }
6902 #else /* not USE_TOOLKIT_SCROLL_BARS */
6903 if (bar)
6904 x_scroll_bar_handle_click (bar, &event, &inev.ie);
6905 #endif /* not USE_TOOLKIT_SCROLL_BARS */
6906 }
6907
6908 if (event.type == ButtonPress)
6909 {
6910 dpyinfo->grabbed |= (1 << event.xbutton.button);
6911 last_mouse_frame = f;
6912
6913 if (!tool_bar_p)
6914 last_tool_bar_item = -1;
6915 }
6916 else
6917 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
6918
6919 /* Ignore any mouse motion that happened before this event;
6920 any subsequent mouse-movement Emacs events should reflect
6921 only motion after the ButtonPress/Release. */
6922 if (f != 0)
6923 f->mouse_moved = 0;
6924
6925 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6926 f = x_menubar_window_to_frame (dpyinfo, &event);
6927 /* For a down-event in the menu bar,
6928 don't pass it to Xt right now.
6929 Instead, save it away
6930 and we will pass it to Xt from kbd_buffer_get_event.
6931 That way, we can run some Lisp code first. */
6932 if (! popup_activated ()
6933 #ifdef USE_GTK
6934 /* Gtk+ menus only react to the first three buttons. */
6935 && event.xbutton.button < 3
6936 #endif
6937 && f && event.type == ButtonPress
6938 /* Verify the event is really within the menu bar
6939 and not just sent to it due to grabbing. */
6940 && event.xbutton.x >= 0
6941 && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
6942 && event.xbutton.y >= 0
6943 && event.xbutton.y < f->output_data.x->menubar_height
6944 && event.xbutton.same_screen)
6945 {
6946 SET_SAVED_BUTTON_EVENT;
6947 *finish = X_EVENT_DROP;
6948 }
6949 else
6950 goto OTHER;
6951 #endif /* USE_X_TOOLKIT || USE_GTK */
6952 }
6953 break;
6954
6955 case CirculateNotify:
6956 goto OTHER;
6957
6958 case CirculateRequest:
6959 goto OTHER;
6960
6961 case VisibilityNotify:
6962 goto OTHER;
6963
6964 case MappingNotify:
6965 /* Someone has changed the keyboard mapping - update the
6966 local cache. */
6967 switch (event.xmapping.request)
6968 {
6969 case MappingModifier:
6970 x_find_modifier_meanings (dpyinfo);
6971 /* This is meant to fall through. */
6972 case MappingKeyboard:
6973 XRefreshKeyboardMapping (&event.xmapping);
6974 }
6975 goto OTHER;
6976
6977 case DestroyNotify:
6978 xft_settings_event (dpyinfo, &event);
6979 break;
6980
6981 default:
6982 OTHER:
6983 #ifdef USE_X_TOOLKIT
6984 block_input ();
6985 if (*finish != X_EVENT_DROP)
6986 XtDispatchEvent (&event);
6987 unblock_input ();
6988 #endif /* USE_X_TOOLKIT */
6989 break;
6990 }
6991
6992 done:
6993 if (inev.ie.kind != NO_EVENT)
6994 {
6995 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
6996 count++;
6997 }
6998
6999 if (do_help
7000 && !(hold_quit && hold_quit->kind != NO_EVENT))
7001 {
7002 Lisp_Object frame;
7003
7004 if (f)
7005 XSETFRAME (frame, f);
7006 else
7007 frame = Qnil;
7008
7009 if (do_help > 0)
7010 {
7011 any_help_event_p = 1;
7012 gen_help_event (help_echo_string, frame, help_echo_window,
7013 help_echo_object, help_echo_pos);
7014 }
7015 else
7016 {
7017 help_echo_string = Qnil;
7018 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
7019 }
7020 count++;
7021 }
7022
7023 SAFE_FREE ();
7024 *eventptr = event;
7025 return count;
7026 }
7027
7028 #if defined USE_GTK || defined USE_X_TOOLKIT
7029
7030 /* Handles the XEvent EVENT on display DISPLAY.
7031 This is used for event loops outside the normal event handling,
7032 i.e. looping while a popup menu or a dialog is posted.
7033
7034 Returns the value handle_one_xevent sets in the finish argument. */
7035 int
7036 x_dispatch_event (XEvent *event, Display *display)
7037 {
7038 struct x_display_info *dpyinfo;
7039 int finish = X_EVENT_NORMAL;
7040
7041 dpyinfo = x_display_info_for_display (display);
7042
7043 if (dpyinfo)
7044 handle_one_xevent (dpyinfo, event, &finish, 0);
7045
7046 return finish;
7047 }
7048 #endif
7049
7050
7051 /* Read events coming from the X server.
7052 Return as soon as there are no more events to be read.
7053
7054 Return the number of characters stored into the buffer,
7055 thus pretending to be `read' (except the characters we store
7056 in the keyboard buffer can be multibyte, so are not necessarily
7057 C chars). */
7058
7059 static int
7060 XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
7061 {
7062 int count = 0;
7063 int event_found = 0;
7064
7065 block_input ();
7066
7067 /* So people can tell when we have read the available input. */
7068 input_signal_count++;
7069
7070 /* For debugging, this gives a way to fake an I/O error. */
7071 if (terminal->display_info.x == XTread_socket_fake_io_error)
7072 {
7073 XTread_socket_fake_io_error = 0;
7074 x_io_error_quitter (terminal->display_info.x->display);
7075 }
7076
7077 #ifndef USE_GTK
7078 while (XPending (terminal->display_info.x->display))
7079 {
7080 int finish;
7081 XEvent event;
7082
7083 XNextEvent (terminal->display_info.x->display, &event);
7084
7085 #ifdef HAVE_X_I18N
7086 /* Filter events for the current X input method. */
7087 if (x_filter_event (terminal->display_info.x, &event))
7088 continue;
7089 #endif
7090 event_found = 1;
7091
7092 count += handle_one_xevent (terminal->display_info.x,
7093 &event, &finish, hold_quit);
7094
7095 if (finish == X_EVENT_GOTO_OUT)
7096 goto out;
7097 }
7098
7099 out:;
7100
7101 #else /* USE_GTK */
7102
7103 /* For GTK we must use the GTK event loop. But XEvents gets passed
7104 to our filter function above, and then to the big event switch.
7105 We use a bunch of globals to communicate with our filter function,
7106 that is kind of ugly, but it works.
7107
7108 There is no way to do one display at the time, GTK just does events
7109 from all displays. */
7110
7111 while (gtk_events_pending ())
7112 {
7113 current_count = count;
7114 current_hold_quit = hold_quit;
7115
7116 gtk_main_iteration ();
7117
7118 count = current_count;
7119 current_count = -1;
7120 current_hold_quit = 0;
7121
7122 if (current_finish == X_EVENT_GOTO_OUT)
7123 break;
7124 }
7125 #endif /* USE_GTK */
7126
7127 /* On some systems, an X bug causes Emacs to get no more events
7128 when the window is destroyed. Detect that. (1994.) */
7129 if (! event_found)
7130 {
7131 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
7132 One XNOOP in 100 loops will make Emacs terminate.
7133 B. Bretthauer, 1994 */
7134 x_noop_count++;
7135 if (x_noop_count >= 100)
7136 {
7137 x_noop_count=0;
7138
7139 if (next_noop_dpyinfo == 0)
7140 next_noop_dpyinfo = x_display_list;
7141
7142 XNoOp (next_noop_dpyinfo->display);
7143
7144 /* Each time we get here, cycle through the displays now open. */
7145 next_noop_dpyinfo = next_noop_dpyinfo->next;
7146 }
7147 }
7148
7149 /* If the focus was just given to an auto-raising frame,
7150 raise it now. */
7151 /* ??? This ought to be able to handle more than one such frame. */
7152 if (pending_autoraise_frame)
7153 {
7154 x_raise_frame (pending_autoraise_frame);
7155 pending_autoraise_frame = 0;
7156 }
7157
7158 unblock_input ();
7159
7160 return count;
7161 }
7162
7163
7164
7165 \f
7166 /***********************************************************************
7167 Text Cursor
7168 ***********************************************************************/
7169
7170 /* Set clipping for output in glyph row ROW. W is the window in which
7171 we operate. GC is the graphics context to set clipping in.
7172
7173 ROW may be a text row or, e.g., a mode line. Text rows must be
7174 clipped to the interior of the window dedicated to text display,
7175 mode lines must be clipped to the whole window. */
7176
7177 static void
7178 x_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
7179 {
7180 struct frame *f = XFRAME (WINDOW_FRAME (w));
7181 XRectangle clip_rect;
7182 int window_x, window_y, window_width;
7183
7184 window_box (w, area, &window_x, &window_y, &window_width, 0);
7185
7186 clip_rect.x = window_x;
7187 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
7188 clip_rect.y = max (clip_rect.y, window_y);
7189 clip_rect.width = window_width;
7190 clip_rect.height = row->visible_height;
7191
7192 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
7193 }
7194
7195
7196 /* Draw a hollow box cursor on window W in glyph row ROW. */
7197
7198 static void
7199 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
7200 {
7201 struct frame *f = XFRAME (WINDOW_FRAME (w));
7202 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7203 Display *dpy = FRAME_X_DISPLAY (f);
7204 int x, y, wd, h;
7205 XGCValues xgcv;
7206 struct glyph *cursor_glyph;
7207 GC gc;
7208
7209 /* Get the glyph the cursor is on. If we can't tell because
7210 the current matrix is invalid or such, give up. */
7211 cursor_glyph = get_phys_cursor_glyph (w);
7212 if (cursor_glyph == NULL)
7213 return;
7214
7215 /* Compute frame-relative coordinates for phys cursor. */
7216 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
7217 wd = w->phys_cursor_width;
7218
7219 /* The foreground of cursor_gc is typically the same as the normal
7220 background color, which can cause the cursor box to be invisible. */
7221 xgcv.foreground = f->output_data.x->cursor_pixel;
7222 if (dpyinfo->scratch_cursor_gc)
7223 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
7224 else
7225 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
7226 GCForeground, &xgcv);
7227 gc = dpyinfo->scratch_cursor_gc;
7228
7229 /* Set clipping, draw the rectangle, and reset clipping again. */
7230 x_clip_to_row (w, row, TEXT_AREA, gc);
7231 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
7232 XSetClipMask (dpy, gc, None);
7233 }
7234
7235
7236 /* Draw a bar cursor on window W in glyph row ROW.
7237
7238 Implementation note: One would like to draw a bar cursor with an
7239 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7240 Unfortunately, I didn't find a font yet that has this property set.
7241 --gerd. */
7242
7243 static void
7244 x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind)
7245 {
7246 struct frame *f = XFRAME (w->frame);
7247 struct glyph *cursor_glyph;
7248
7249 /* If cursor is out of bounds, don't draw garbage. This can happen
7250 in mini-buffer windows when switching between echo area glyphs
7251 and mini-buffer. */
7252 cursor_glyph = get_phys_cursor_glyph (w);
7253 if (cursor_glyph == NULL)
7254 return;
7255
7256 /* If on an image, draw like a normal cursor. That's usually better
7257 visible than drawing a bar, esp. if the image is large so that
7258 the bar might not be in the window. */
7259 if (cursor_glyph->type == IMAGE_GLYPH)
7260 {
7261 struct glyph_row *r;
7262 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7263 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
7264 }
7265 else
7266 {
7267 Display *dpy = FRAME_X_DISPLAY (f);
7268 Window window = FRAME_X_WINDOW (f);
7269 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
7270 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
7271 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7272 XGCValues xgcv;
7273
7274 /* If the glyph's background equals the color we normally draw
7275 the bars cursor in, the bar cursor in its normal color is
7276 invisible. Use the glyph's foreground color instead in this
7277 case, on the assumption that the glyph's colors are chosen so
7278 that the glyph is legible. */
7279 if (face->background == f->output_data.x->cursor_pixel)
7280 xgcv.background = xgcv.foreground = face->foreground;
7281 else
7282 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
7283 xgcv.graphics_exposures = 0;
7284
7285 if (gc)
7286 XChangeGC (dpy, gc, mask, &xgcv);
7287 else
7288 {
7289 gc = XCreateGC (dpy, window, mask, &xgcv);
7290 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
7291 }
7292
7293 x_clip_to_row (w, row, TEXT_AREA, gc);
7294
7295 if (kind == BAR_CURSOR)
7296 {
7297 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7298
7299 if (width < 0)
7300 width = FRAME_CURSOR_WIDTH (f);
7301 width = min (cursor_glyph->pixel_width, width);
7302
7303 w->phys_cursor_width = width;
7304
7305 /* If the character under cursor is R2L, draw the bar cursor
7306 on the right of its glyph, rather than on the left. */
7307 if ((cursor_glyph->resolved_level & 1) != 0)
7308 x += cursor_glyph->pixel_width - width;
7309
7310 XFillRectangle (dpy, window, gc, x,
7311 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7312 width, row->height);
7313 }
7314 else
7315 {
7316 int dummy_x, dummy_y, dummy_h;
7317
7318 if (width < 0)
7319 width = row->height;
7320
7321 width = min (row->height, width);
7322
7323 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
7324 &dummy_y, &dummy_h);
7325
7326 XFillRectangle (dpy, window, gc,
7327 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
7328 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7329 row->height - width),
7330 w->phys_cursor_width, width);
7331 }
7332
7333 XSetClipMask (dpy, gc, None);
7334 }
7335 }
7336
7337
7338 /* RIF: Define cursor CURSOR on frame F. */
7339
7340 static void
7341 x_define_frame_cursor (struct frame *f, Cursor cursor)
7342 {
7343 if (!f->pointer_invisible
7344 && f->output_data.x->current_cursor != cursor)
7345 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7346 f->output_data.x->current_cursor = cursor;
7347 }
7348
7349
7350 /* RIF: Clear area on frame F. */
7351
7352 static void
7353 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
7354 {
7355 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7356 x, y, width, height, False);
7357 #ifdef USE_GTK
7358 /* Must queue a redraw, because scroll bars might have been cleared. */
7359 if (FRAME_GTK_WIDGET (f))
7360 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
7361 #endif
7362 }
7363
7364
7365 /* RIF: Draw cursor on window W. */
7366
7367 static void
7368 x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
7369 int y, enum text_cursor_kinds cursor_type,
7370 int cursor_width, bool on_p, bool active_p)
7371 {
7372 struct frame *f = XFRAME (WINDOW_FRAME (w));
7373
7374 if (on_p)
7375 {
7376 w->phys_cursor_type = cursor_type;
7377 w->phys_cursor_on_p = 1;
7378
7379 if (glyph_row->exact_window_width_line_p
7380 && (glyph_row->reversed_p
7381 ? (w->phys_cursor.hpos < 0)
7382 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
7383 {
7384 glyph_row->cursor_in_fringe_p = 1;
7385 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
7386 }
7387 else
7388 {
7389 switch (cursor_type)
7390 {
7391 case HOLLOW_BOX_CURSOR:
7392 x_draw_hollow_cursor (w, glyph_row);
7393 break;
7394
7395 case FILLED_BOX_CURSOR:
7396 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7397 break;
7398
7399 case BAR_CURSOR:
7400 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
7401 break;
7402
7403 case HBAR_CURSOR:
7404 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
7405 break;
7406
7407 case NO_CURSOR:
7408 w->phys_cursor_width = 0;
7409 break;
7410
7411 default:
7412 emacs_abort ();
7413 }
7414 }
7415
7416 #ifdef HAVE_X_I18N
7417 if (w == XWINDOW (f->selected_window))
7418 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
7419 xic_set_preeditarea (w, x, y);
7420 #endif
7421 }
7422
7423 #ifndef XFlush
7424 XFlush (FRAME_X_DISPLAY (f));
7425 #endif
7426 }
7427
7428 \f
7429 /* Icons. */
7430
7431 /* Make the x-window of frame F use the gnu icon bitmap. */
7432
7433 int
7434 x_bitmap_icon (struct frame *f, Lisp_Object file)
7435 {
7436 ptrdiff_t bitmap_id;
7437
7438 if (FRAME_X_WINDOW (f) == 0)
7439 return 1;
7440
7441 /* Free up our existing icon bitmap and mask if any. */
7442 if (f->output_data.x->icon_bitmap > 0)
7443 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7444 f->output_data.x->icon_bitmap = 0;
7445
7446 if (STRINGP (file))
7447 {
7448 #ifdef USE_GTK
7449 /* Use gtk_window_set_icon_from_file () if available,
7450 It's not restricted to bitmaps */
7451 if (xg_set_icon (f, file))
7452 return 0;
7453 #endif /* USE_GTK */
7454 bitmap_id = x_create_bitmap_from_file (f, file);
7455 x_create_bitmap_mask (f, bitmap_id);
7456 }
7457 else
7458 {
7459 /* Create the GNU bitmap and mask if necessary. */
7460 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
7461 {
7462 ptrdiff_t rc = -1;
7463
7464 #ifdef USE_GTK
7465
7466 if (xg_set_icon (f, xg_default_icon_file)
7467 || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
7468 return 0;
7469
7470 #elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
7471
7472 rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
7473 if (rc != -1)
7474 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7475
7476 #endif
7477
7478 /* If all else fails, use the (black and white) xbm image. */
7479 if (rc == -1)
7480 {
7481 rc = x_create_bitmap_from_data (f, (char *) gnu_xbm_bits,
7482 gnu_xbm_width, gnu_xbm_height);
7483 if (rc == -1)
7484 return 1;
7485
7486 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
7487 x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7488 }
7489 }
7490
7491 /* The first time we create the GNU bitmap and mask,
7492 this increments the ref-count one extra time.
7493 As a result, the GNU bitmap and mask are never freed.
7494 That way, we don't have to worry about allocating it again. */
7495 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
7496
7497 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7498 }
7499
7500 x_wm_set_icon_pixmap (f, bitmap_id);
7501 f->output_data.x->icon_bitmap = bitmap_id;
7502
7503 return 0;
7504 }
7505
7506
7507 /* Make the x-window of frame F use a rectangle with text.
7508 Use ICON_NAME as the text. */
7509
7510 int
7511 x_text_icon (struct frame *f, const char *icon_name)
7512 {
7513 if (FRAME_X_WINDOW (f) == 0)
7514 return 1;
7515
7516 {
7517 XTextProperty text;
7518 text.value = (unsigned char *) icon_name;
7519 text.encoding = XA_STRING;
7520 text.format = 8;
7521 text.nitems = strlen (icon_name);
7522 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
7523 }
7524
7525 if (f->output_data.x->icon_bitmap > 0)
7526 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
7527 f->output_data.x->icon_bitmap = 0;
7528 x_wm_set_icon_pixmap (f, 0);
7529
7530 return 0;
7531 }
7532 \f
7533 #define X_ERROR_MESSAGE_SIZE 200
7534
7535 /* If non-nil, this should be a string.
7536 It means catch X errors and store the error message in this string.
7537
7538 The reason we use a stack is that x_catch_error/x_uncatch_error can
7539 be called from a signal handler.
7540 */
7541
7542 struct x_error_message_stack {
7543 char string[X_ERROR_MESSAGE_SIZE];
7544 Display *dpy;
7545 struct x_error_message_stack *prev;
7546 };
7547 static struct x_error_message_stack *x_error_message;
7548
7549 /* An X error handler which stores the error message in
7550 *x_error_message. This is called from x_error_handler if
7551 x_catch_errors is in effect. */
7552
7553 static void
7554 x_error_catcher (Display *display, XErrorEvent *event)
7555 {
7556 XGetErrorText (display, event->error_code,
7557 x_error_message->string,
7558 X_ERROR_MESSAGE_SIZE);
7559 }
7560
7561 /* Begin trapping X errors for display DPY. Actually we trap X errors
7562 for all displays, but DPY should be the display you are actually
7563 operating on.
7564
7565 After calling this function, X protocol errors no longer cause
7566 Emacs to exit; instead, they are recorded in the string
7567 stored in *x_error_message.
7568
7569 Calling x_check_errors signals an Emacs error if an X error has
7570 occurred since the last call to x_catch_errors or x_check_errors.
7571
7572 Calling x_uncatch_errors resumes the normal error handling. */
7573
7574 void
7575 x_catch_errors (Display *dpy)
7576 {
7577 struct x_error_message_stack *data = xmalloc (sizeof *data);
7578
7579 /* Make sure any errors from previous requests have been dealt with. */
7580 XSync (dpy, False);
7581
7582 data->dpy = dpy;
7583 data->string[0] = 0;
7584 data->prev = x_error_message;
7585 x_error_message = data;
7586 }
7587
7588 /* Undo the last x_catch_errors call.
7589 DPY should be the display that was passed to x_catch_errors. */
7590
7591 void
7592 x_uncatch_errors (void)
7593 {
7594 struct x_error_message_stack *tmp;
7595
7596 block_input ();
7597
7598 /* The display may have been closed before this function is called.
7599 Check if it is still open before calling XSync. */
7600 if (x_display_info_for_display (x_error_message->dpy) != 0)
7601 XSync (x_error_message->dpy, False);
7602
7603 tmp = x_error_message;
7604 x_error_message = x_error_message->prev;
7605 xfree (tmp);
7606 unblock_input ();
7607 }
7608
7609 /* If any X protocol errors have arrived since the last call to
7610 x_catch_errors or x_check_errors, signal an Emacs error using
7611 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7612
7613 void
7614 x_check_errors (Display *dpy, const char *format)
7615 {
7616 /* Make sure to catch any errors incurred so far. */
7617 XSync (dpy, False);
7618
7619 if (x_error_message->string[0])
7620 {
7621 char string[X_ERROR_MESSAGE_SIZE];
7622 memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE);
7623 x_uncatch_errors ();
7624 error (format, string);
7625 }
7626 }
7627
7628 /* Nonzero if we had any X protocol errors
7629 since we did x_catch_errors on DPY. */
7630
7631 bool
7632 x_had_errors_p (Display *dpy)
7633 {
7634 /* Make sure to catch any errors incurred so far. */
7635 XSync (dpy, False);
7636
7637 return x_error_message->string[0] != 0;
7638 }
7639
7640 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7641
7642 void
7643 x_clear_errors (Display *dpy)
7644 {
7645 x_error_message->string[0] = 0;
7646 }
7647
7648 #if 0 /* See comment in unwind_to_catch why calling this is a bad
7649 * idea. --lorentey */
7650 /* Close off all unclosed x_catch_errors calls. */
7651
7652 void
7653 x_fully_uncatch_errors (void)
7654 {
7655 while (x_error_message)
7656 x_uncatch_errors ();
7657 }
7658 #endif
7659
7660 #if 0
7661 static unsigned int x_wire_count;
7662 x_trace_wire (void)
7663 {
7664 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
7665 }
7666 #endif /* ! 0 */
7667
7668 \f
7669 /************************************************************************
7670 Handling X errors
7671 ************************************************************************/
7672
7673 /* Error message passed to x_connection_closed. */
7674
7675 static char *error_msg;
7676
7677 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7678 the text of an error message that lead to the connection loss. */
7679
7680 static void
7681 x_connection_closed (Display *dpy, const char *error_message)
7682 {
7683 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7684 Lisp_Object frame, tail;
7685 ptrdiff_t idx = SPECPDL_INDEX ();
7686
7687 error_msg = alloca (strlen (error_message) + 1);
7688 strcpy (error_msg, error_message);
7689
7690 /* Inhibit redisplay while frames are being deleted. */
7691 specbind (Qinhibit_redisplay, Qt);
7692
7693 if (dpyinfo)
7694 {
7695 /* Protect display from being closed when we delete the last
7696 frame on it. */
7697 dpyinfo->reference_count++;
7698 dpyinfo->terminal->reference_count++;
7699 }
7700
7701 /* First delete frames whose mini-buffers are on frames
7702 that are on the dead display. */
7703 FOR_EACH_FRAME (tail, frame)
7704 {
7705 Lisp_Object minibuf_frame;
7706 minibuf_frame
7707 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
7708 if (FRAME_X_P (XFRAME (frame))
7709 && FRAME_X_P (XFRAME (minibuf_frame))
7710 && ! EQ (frame, minibuf_frame)
7711 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7712 delete_frame (frame, Qnoelisp);
7713 }
7714
7715 /* Now delete all remaining frames on the dead display.
7716 We are now sure none of these is used as the mini-buffer
7717 for another frame that we need to delete. */
7718 FOR_EACH_FRAME (tail, frame)
7719 if (FRAME_X_P (XFRAME (frame))
7720 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
7721 {
7722 /* Set this to t so that delete_frame won't get confused
7723 trying to find a replacement. */
7724 kset_default_minibuffer_frame (FRAME_KBOARD (XFRAME (frame)), Qt);
7725 delete_frame (frame, Qnoelisp);
7726 }
7727
7728 /* If DPYINFO is null, this means we didn't open the display in the
7729 first place, so don't try to close it. */
7730 if (dpyinfo)
7731 {
7732 /* We can not call XtCloseDisplay here because it calls XSync.
7733 XSync inside the error handler apparently hangs Emacs. On
7734 current Xt versions, this isn't needed either. */
7735 #ifdef USE_GTK
7736 /* A long-standing GTK bug prevents proper disconnect handling
7737 (https://bugzilla.gnome.org/show_bug.cgi?id=85715). Once,
7738 the resulting Glib error message loop filled a user's disk.
7739 To avoid this, kill Emacs unconditionally on disconnect. */
7740 shut_down_emacs (0, Qnil);
7741 fprintf (stderr, "%s\n\
7742 When compiled with GTK, Emacs cannot recover from X disconnects.\n\
7743 This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
7744 For details, see etc/PROBLEMS.\n",
7745 error_msg);
7746 emacs_abort ();
7747 #endif /* USE_GTK */
7748
7749 /* Indicate that this display is dead. */
7750 dpyinfo->display = 0;
7751
7752 dpyinfo->reference_count--;
7753 dpyinfo->terminal->reference_count--;
7754 if (dpyinfo->reference_count != 0)
7755 /* We have just closed all frames on this display. */
7756 emacs_abort ();
7757
7758 {
7759 Lisp_Object tmp;
7760 XSETTERMINAL (tmp, dpyinfo->terminal);
7761 Fdelete_terminal (tmp, Qnoelisp);
7762 }
7763 }
7764
7765 if (terminal_list == 0)
7766 {
7767 fprintf (stderr, "%s\n", error_msg);
7768 Fkill_emacs (make_number (70));
7769 /* NOTREACHED */
7770 }
7771
7772 totally_unblock_input ();
7773
7774 unbind_to (idx, Qnil);
7775 clear_waiting_for_input ();
7776
7777 /* Tell GCC not to suggest attribute 'noreturn' for this function. */
7778 IF_LINT (if (! terminal_list) return; )
7779
7780 /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
7781 longjmp), because returning from this function would get us back into
7782 Xlib's code which will directly call `exit'. */
7783 error ("%s", error_msg);
7784 }
7785
7786 /* We specifically use it before defining it, so that gcc doesn't inline it,
7787 otherwise gdb doesn't know how to properly put a breakpoint on it. */
7788 static void x_error_quitter (Display *, XErrorEvent *);
7789
7790 /* This is the first-level handler for X protocol errors.
7791 It calls x_error_quitter or x_error_catcher. */
7792
7793 static int
7794 x_error_handler (Display *display, XErrorEvent *event)
7795 {
7796 #if defined USE_GTK && defined HAVE_GTK3
7797 if ((event->error_code == BadMatch || event->error_code == BadWindow)
7798 && event->request_code == X_SetInputFocus)
7799 {
7800 return 0;
7801 }
7802 #endif
7803
7804 if (x_error_message)
7805 x_error_catcher (display, event);
7806 else
7807 x_error_quitter (display, event);
7808 return 0;
7809 }
7810
7811 /* This is the usual handler for X protocol errors.
7812 It kills all frames on the display that we got the error for.
7813 If that was the only one, it prints an error message and kills Emacs. */
7814
7815 /* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
7816
7817 /* On older GCC versions, just putting x_error_quitter
7818 after x_error_handler prevents inlining into the former. */
7819
7820 static void NO_INLINE
7821 x_error_quitter (Display *display, XErrorEvent *event)
7822 {
7823 char buf[256], buf1[356];
7824
7825 /* Ignore BadName errors. They can happen because of fonts
7826 or colors that are not defined. */
7827
7828 if (event->error_code == BadName)
7829 return;
7830
7831 /* Note that there is no real way portable across R3/R4 to get the
7832 original error handler. */
7833
7834 XGetErrorText (display, event->error_code, buf, sizeof (buf));
7835 sprintf (buf1, "X protocol error: %s on protocol request %d",
7836 buf, event->request_code);
7837 x_connection_closed (display, buf1);
7838 }
7839
7840
7841 /* This is the handler for X IO errors, always.
7842 It kills all frames on the display that we lost touch with.
7843 If that was the only one, it prints an error message and kills Emacs. */
7844
7845 static int
7846 x_io_error_quitter (Display *display)
7847 {
7848 char buf[256];
7849
7850 snprintf (buf, sizeof buf, "Connection lost to X server `%s'",
7851 DisplayString (display));
7852 x_connection_closed (display, buf);
7853 return 0;
7854 }
7855 \f
7856 /* Changing the font of the frame. */
7857
7858 /* Give frame F the font FONT-OBJECT as its default font. The return
7859 value is FONT-OBJECT. FONTSET is an ID of the fontset for the
7860 frame. If it is negative, generate a new fontset from
7861 FONT-OBJECT. */
7862
7863 Lisp_Object
7864 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7865 {
7866 struct font *font = XFONT_OBJECT (font_object);
7867
7868 if (fontset < 0)
7869 fontset = fontset_from_font (font_object);
7870 FRAME_FONTSET (f) = fontset;
7871 if (FRAME_FONT (f) == font)
7872 /* This font is already set in frame F. There's nothing more to
7873 do. */
7874 return font_object;
7875
7876 FRAME_FONT (f) = font;
7877 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
7878 FRAME_COLUMN_WIDTH (f) = font->average_width;
7879 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
7880
7881 compute_fringe_widths (f, 1);
7882
7883 /* Compute the scroll bar width in character columns. */
7884 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
7885 {
7886 int wid = FRAME_COLUMN_WIDTH (f);
7887 FRAME_CONFIG_SCROLL_BAR_COLS (f)
7888 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
7889 }
7890 else
7891 {
7892 int wid = FRAME_COLUMN_WIDTH (f);
7893 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
7894 }
7895
7896 if (FRAME_X_WINDOW (f) != 0)
7897 {
7898 /* Don't change the size of a tip frame; there's no point in
7899 doing it because it's done in Fx_show_tip, and it leads to
7900 problems because the tip frame has no widget. */
7901 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
7902 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
7903 }
7904
7905 #ifdef HAVE_X_I18N
7906 if (FRAME_XIC (f)
7907 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
7908 {
7909 block_input ();
7910 xic_set_xfontset (f, SSDATA (fontset_ascii (fontset)));
7911 unblock_input ();
7912 }
7913 #endif
7914
7915 return font_object;
7916 }
7917
7918 \f
7919 /***********************************************************************
7920 X Input Methods
7921 ***********************************************************************/
7922
7923 #ifdef HAVE_X_I18N
7924
7925 #ifdef HAVE_X11R6
7926
7927 /* XIM destroy callback function, which is called whenever the
7928 connection to input method XIM dies. CLIENT_DATA contains a
7929 pointer to the x_display_info structure corresponding to XIM. */
7930
7931 static void
7932 xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
7933 {
7934 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
7935 Lisp_Object frame, tail;
7936
7937 block_input ();
7938
7939 /* No need to call XDestroyIC.. */
7940 FOR_EACH_FRAME (tail, frame)
7941 {
7942 struct frame *f = XFRAME (frame);
7943 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
7944 {
7945 FRAME_XIC (f) = NULL;
7946 xic_free_xfontset (f);
7947 }
7948 }
7949
7950 /* No need to call XCloseIM. */
7951 dpyinfo->xim = NULL;
7952 XFree (dpyinfo->xim_styles);
7953 unblock_input ();
7954 }
7955
7956 #endif /* HAVE_X11R6 */
7957
7958 #ifdef HAVE_X11R6
7959 /* This isn't prototyped in OSF 5.0 or 5.1a. */
7960 extern char *XSetIMValues (XIM, ...);
7961 #endif
7962
7963 /* Open the connection to the XIM server on display DPYINFO.
7964 RESOURCE_NAME is the resource name Emacs uses. */
7965
7966 static void
7967 xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
7968 {
7969 XIM xim;
7970
7971 #ifdef HAVE_XIM
7972 if (use_xim)
7973 {
7974 if (dpyinfo->xim)
7975 XCloseIM (dpyinfo->xim);
7976 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
7977 emacs_class);
7978 dpyinfo->xim = xim;
7979
7980 if (xim)
7981 {
7982 #ifdef HAVE_X11R6
7983 XIMCallback destroy;
7984 #endif
7985
7986 /* Get supported styles and XIM values. */
7987 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
7988
7989 #ifdef HAVE_X11R6
7990 destroy.callback = xim_destroy_callback;
7991 destroy.client_data = (XPointer)dpyinfo;
7992 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
7993 #endif
7994 }
7995 }
7996
7997 else
7998 #endif /* HAVE_XIM */
7999 dpyinfo->xim = NULL;
8000 }
8001
8002
8003 #ifdef HAVE_X11R6_XIM
8004
8005 /* XIM instantiate callback function, which is called whenever an XIM
8006 server is available. DISPLAY is the display of the XIM.
8007 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8008 when the callback was registered. */
8009
8010 static void
8011 xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_data)
8012 {
8013 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
8014 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
8015
8016 /* We don't support multiple XIM connections. */
8017 if (dpyinfo->xim)
8018 return;
8019
8020 xim_open_dpy (dpyinfo, xim_inst->resource_name);
8021
8022 /* Create XIC for the existing frames on the same display, as long
8023 as they have no XIC. */
8024 if (dpyinfo->xim && dpyinfo->reference_count > 0)
8025 {
8026 Lisp_Object tail, frame;
8027
8028 block_input ();
8029 FOR_EACH_FRAME (tail, frame)
8030 {
8031 struct frame *f = XFRAME (frame);
8032
8033 if (FRAME_X_P (f)
8034 && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8035 if (FRAME_XIC (f) == NULL)
8036 {
8037 create_frame_xic (f);
8038 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
8039 xic_set_statusarea (f);
8040 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
8041 {
8042 struct window *w = XWINDOW (f->selected_window);
8043 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
8044 }
8045 }
8046 }
8047
8048 unblock_input ();
8049 }
8050 }
8051
8052 #endif /* HAVE_X11R6_XIM */
8053
8054
8055 /* Open a connection to the XIM server on display DPYINFO.
8056 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8057 connection only at the first time. On X11R6, open the connection
8058 in the XIM instantiate callback function. */
8059
8060 static void
8061 xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
8062 {
8063 dpyinfo->xim = NULL;
8064 #ifdef HAVE_XIM
8065 if (use_xim)
8066 {
8067 #ifdef HAVE_X11R6_XIM
8068 struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
8069
8070 dpyinfo->xim_callback_data = xim_inst;
8071 xim_inst->dpyinfo = dpyinfo;
8072 xim_inst->resource_name = xstrdup (resource_name);
8073 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8074 resource_name, emacs_class,
8075 xim_instantiate_callback,
8076 /* This is XPointer in XFree86
8077 but (XPointer *) on Tru64, at
8078 least, hence the configure test. */
8079 (XRegisterIMInstantiateCallback_arg6) xim_inst);
8080 #else /* not HAVE_X11R6_XIM */
8081 xim_open_dpy (dpyinfo, resource_name);
8082 #endif /* not HAVE_X11R6_XIM */
8083 }
8084 #endif /* HAVE_XIM */
8085 }
8086
8087
8088 /* Close the connection to the XIM server on display DPYINFO. */
8089
8090 static void
8091 xim_close_dpy (struct x_display_info *dpyinfo)
8092 {
8093 #ifdef HAVE_XIM
8094 if (use_xim)
8095 {
8096 #ifdef HAVE_X11R6_XIM
8097 if (dpyinfo->display)
8098 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8099 NULL, emacs_class,
8100 xim_instantiate_callback, NULL);
8101 xfree (dpyinfo->xim_callback_data->resource_name);
8102 xfree (dpyinfo->xim_callback_data);
8103 #endif /* HAVE_X11R6_XIM */
8104 if (dpyinfo->display)
8105 XCloseIM (dpyinfo->xim);
8106 dpyinfo->xim = NULL;
8107 XFree (dpyinfo->xim_styles);
8108 }
8109 #endif /* HAVE_XIM */
8110 }
8111
8112 #endif /* not HAVE_X11R6_XIM */
8113
8114
8115 \f
8116 /* Calculate the absolute position in frame F
8117 from its current recorded position values and gravity. */
8118
8119 static void
8120 x_calc_absolute_position (struct frame *f)
8121 {
8122 int flags = f->size_hint_flags;
8123
8124 /* We have nothing to do if the current position
8125 is already for the top-left corner. */
8126 if (! ((flags & XNegative) || (flags & YNegative)))
8127 return;
8128
8129 /* Treat negative positions as relative to the leftmost bottommost
8130 position that fits on the screen. */
8131 if (flags & XNegative)
8132 f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
8133 - FRAME_PIXEL_WIDTH (f) + f->left_pos;
8134
8135 {
8136 int height = FRAME_PIXEL_HEIGHT (f);
8137
8138 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8139 /* Something is fishy here. When using Motif, starting Emacs with
8140 `-g -0-0', the frame appears too low by a few pixels.
8141
8142 This seems to be so because initially, while Emacs is starting,
8143 the column widget's height and the frame's pixel height are
8144 different. The column widget's height is the right one. In
8145 later invocations, when Emacs is up, the frame's pixel height
8146 is right, though.
8147
8148 It's not obvious where the initial small difference comes from.
8149 2000-12-01, gerd. */
8150
8151 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8152 #endif
8153
8154 if (flags & YNegative)
8155 f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
8156 - height + f->top_pos;
8157 }
8158
8159 /* The left_pos and top_pos
8160 are now relative to the top and left screen edges,
8161 so the flags should correspond. */
8162 f->size_hint_flags &= ~ (XNegative | YNegative);
8163 }
8164
8165 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8166 to really change the position, and 0 when calling from
8167 x_make_frame_visible (in that case, XOFF and YOFF are the current
8168 position values). It is -1 when calling from x_set_frame_parameters,
8169 which means, do adjust for borders but don't change the gravity. */
8170
8171 void
8172 x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
8173 {
8174 int modified_top, modified_left;
8175
8176 if (change_gravity > 0)
8177 {
8178 FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
8179 FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
8180
8181 f->top_pos = yoff;
8182 f->left_pos = xoff;
8183 f->size_hint_flags &= ~ (XNegative | YNegative);
8184 if (xoff < 0)
8185 f->size_hint_flags |= XNegative;
8186 if (yoff < 0)
8187 f->size_hint_flags |= YNegative;
8188 f->win_gravity = NorthWestGravity;
8189 }
8190 x_calc_absolute_position (f);
8191
8192 block_input ();
8193 x_wm_set_size_hint (f, (long) 0, 0);
8194
8195 modified_left = f->left_pos;
8196 modified_top = f->top_pos;
8197
8198 if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8199 {
8200 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8201 than the WM decorations. So we use the calculated offset instead
8202 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8203 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
8204 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
8205 }
8206
8207 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8208 modified_left, modified_top);
8209
8210 x_sync_with_move (f, f->left_pos, f->top_pos,
8211 FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8212 ? 1 : 0);
8213
8214 /* change_gravity is non-zero when this function is called from Lisp to
8215 programmatically move a frame. In that case, we call
8216 x_check_expected_move to discover if we have a "Type A" or "Type B"
8217 window manager, and, for a "Type A" window manager, adjust the position
8218 of the frame.
8219
8220 We call x_check_expected_move if a programmatic move occurred, and
8221 either the window manager type (A/B) is unknown or it is Type A but we
8222 need to compute the top/left offset adjustment for this frame. */
8223
8224 if (change_gravity != 0 &&
8225 (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8226 || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
8227 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
8228 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
8229 x_check_expected_move (f, modified_left, modified_top);
8230
8231 unblock_input ();
8232 }
8233
8234 /* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
8235 on the root window for frame F contains ATOMNAME.
8236 This is how a WM check shall be done according to the Window Manager
8237 Specification/Extended Window Manager Hints at
8238 http://freedesktop.org/wiki/Specifications/wm-spec. */
8239
8240 static int
8241 wm_supports (struct frame *f, Atom want_atom)
8242 {
8243 Atom actual_type;
8244 unsigned long actual_size, bytes_remaining;
8245 int i, rc, actual_format;
8246 Window wmcheck_window;
8247 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8248 Window target_window = dpyinfo->root_window;
8249 long max_len = 65536;
8250 Display *dpy = FRAME_X_DISPLAY (f);
8251 unsigned char *tmp_data = NULL;
8252 Atom target_type = XA_WINDOW;
8253
8254 block_input ();
8255
8256 x_catch_errors (dpy);
8257 rc = XGetWindowProperty (dpy, target_window,
8258 dpyinfo->Xatom_net_supporting_wm_check,
8259 0, max_len, False, target_type,
8260 &actual_type, &actual_format, &actual_size,
8261 &bytes_remaining, &tmp_data);
8262
8263 if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
8264 {
8265 if (tmp_data) XFree (tmp_data);
8266 x_uncatch_errors ();
8267 unblock_input ();
8268 return 0;
8269 }
8270
8271 wmcheck_window = *(Window *) tmp_data;
8272 XFree (tmp_data);
8273
8274 /* Check if window exists. */
8275 XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
8276 x_sync (f);
8277 if (x_had_errors_p (dpy))
8278 {
8279 x_uncatch_errors ();
8280 unblock_input ();
8281 return 0;
8282 }
8283
8284 if (dpyinfo->net_supported_window != wmcheck_window)
8285 {
8286 /* Window changed, reload atoms */
8287 if (dpyinfo->net_supported_atoms != NULL)
8288 XFree (dpyinfo->net_supported_atoms);
8289 dpyinfo->net_supported_atoms = NULL;
8290 dpyinfo->nr_net_supported_atoms = 0;
8291 dpyinfo->net_supported_window = 0;
8292
8293 target_type = XA_ATOM;
8294 tmp_data = NULL;
8295 rc = XGetWindowProperty (dpy, target_window,
8296 dpyinfo->Xatom_net_supported,
8297 0, max_len, False, target_type,
8298 &actual_type, &actual_format, &actual_size,
8299 &bytes_remaining, &tmp_data);
8300
8301 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
8302 {
8303 if (tmp_data) XFree (tmp_data);
8304 x_uncatch_errors ();
8305 unblock_input ();
8306 return 0;
8307 }
8308
8309 dpyinfo->net_supported_atoms = (Atom *)tmp_data;
8310 dpyinfo->nr_net_supported_atoms = actual_size;
8311 dpyinfo->net_supported_window = wmcheck_window;
8312 }
8313
8314 rc = 0;
8315
8316 for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
8317 rc = dpyinfo->net_supported_atoms[i] == want_atom;
8318
8319 x_uncatch_errors ();
8320 unblock_input ();
8321
8322 return rc;
8323 }
8324
8325 static void
8326 set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
8327 {
8328 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
8329
8330 x_send_client_event (frame, make_number (0), frame,
8331 dpyinfo->Xatom_net_wm_state,
8332 make_number (32),
8333 /* 1 = add, 0 = remove */
8334 Fcons
8335 (make_number (add ? 1 : 0),
8336 Fcons
8337 (make_fixnum_or_float (atom),
8338 (value != 0
8339 ? list1 (make_fixnum_or_float (value))
8340 : Qnil))));
8341 }
8342
8343 void
8344 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
8345 {
8346 Lisp_Object frame;
8347 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8348
8349 XSETFRAME (frame, f);
8350
8351 set_wm_state (frame, NILP (new_value) ? 0 : 1,
8352 dpyinfo->Xatom_net_wm_state_sticky, None);
8353 }
8354
8355 /* Return the current _NET_WM_STATE.
8356 SIZE_STATE is set to one of the FULLSCREEN_* values.
8357 STICKY is set to 1 if the sticky state is set, 0 if not.
8358
8359 Return non-zero if we are not hidden, zero if we are. */
8360
8361 static int
8362 get_current_wm_state (struct frame *f,
8363 Window window,
8364 int *size_state,
8365 int *sticky)
8366 {
8367 Atom actual_type;
8368 unsigned long actual_size, bytes_remaining;
8369 int i, rc, actual_format, is_hidden = 0;
8370 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8371 long max_len = 65536;
8372 Display *dpy = FRAME_X_DISPLAY (f);
8373 unsigned char *tmp_data = NULL;
8374 Atom target_type = XA_ATOM;
8375
8376 *sticky = 0;
8377 *size_state = FULLSCREEN_NONE;
8378
8379 block_input ();
8380 x_catch_errors (dpy);
8381 rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
8382 0, max_len, False, target_type,
8383 &actual_type, &actual_format, &actual_size,
8384 &bytes_remaining, &tmp_data);
8385
8386 if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
8387 {
8388 if (tmp_data) XFree (tmp_data);
8389 x_uncatch_errors ();
8390 unblock_input ();
8391 return !FRAME_ICONIFIED_P (f);
8392 }
8393
8394 x_uncatch_errors ();
8395
8396 for (i = 0; i < actual_size; ++i)
8397 {
8398 Atom a = ((Atom*)tmp_data)[i];
8399 if (a == dpyinfo->Xatom_net_wm_state_hidden)
8400 {
8401 is_hidden = 1;
8402 f->output_data.x->net_wm_state_hidden_seen = 1;
8403 }
8404 else if (a == dpyinfo->Xatom_net_wm_state_maximized_horz)
8405 {
8406 if (*size_state == FULLSCREEN_HEIGHT)
8407 *size_state = FULLSCREEN_MAXIMIZED;
8408 else
8409 *size_state = FULLSCREEN_WIDTH;
8410 }
8411 else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
8412 {
8413 if (*size_state == FULLSCREEN_WIDTH)
8414 *size_state = FULLSCREEN_MAXIMIZED;
8415 else
8416 *size_state = FULLSCREEN_HEIGHT;
8417 }
8418 else if (a == dpyinfo->Xatom_net_wm_state_fullscreen)
8419 *size_state = FULLSCREEN_BOTH;
8420 else if (a == dpyinfo->Xatom_net_wm_state_sticky)
8421 *sticky = 1;
8422 }
8423
8424 if (tmp_data) XFree (tmp_data);
8425 unblock_input ();
8426 return ! is_hidden;
8427 }
8428
8429 /* Do fullscreen as specified in extended window manager hints */
8430
8431 static int
8432 do_ewmh_fullscreen (struct frame *f)
8433 {
8434 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8435 int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
8436 int cur, dummy;
8437
8438 (void)get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
8439
8440 /* Some window managers don't say they support _NET_WM_STATE, but they do say
8441 they support _NET_WM_STATE_FULLSCREEN. Try that also. */
8442 if (!have_net_atom)
8443 have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state_fullscreen);
8444
8445 if (have_net_atom && cur != f->want_fullscreen)
8446 {
8447 Lisp_Object frame;
8448
8449 XSETFRAME (frame, f);
8450
8451 /* Keep number of calls to set_wm_state as low as possible.
8452 Some window managers, or possible Gtk+, hangs when too many
8453 are sent at once. */
8454 switch (f->want_fullscreen)
8455 {
8456 case FULLSCREEN_BOTH:
8457 if (cur == FULLSCREEN_WIDTH || cur == FULLSCREEN_MAXIMIZED
8458 || cur == FULLSCREEN_HEIGHT)
8459 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
8460 dpyinfo->Xatom_net_wm_state_maximized_vert);
8461 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8462 break;
8463 case FULLSCREEN_WIDTH:
8464 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
8465 || cur == FULLSCREEN_MAXIMIZED)
8466 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
8467 dpyinfo->Xatom_net_wm_state_maximized_vert);
8468 if (cur != FULLSCREEN_MAXIMIZED)
8469 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz, None);
8470 break;
8471 case FULLSCREEN_HEIGHT:
8472 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
8473 || cur == FULLSCREEN_MAXIMIZED)
8474 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen,
8475 dpyinfo->Xatom_net_wm_state_maximized_horz);
8476 if (cur != FULLSCREEN_MAXIMIZED)
8477 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_vert, None);
8478 break;
8479 case FULLSCREEN_MAXIMIZED:
8480 if (cur == FULLSCREEN_BOTH)
8481 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8482 set_wm_state (frame, 1, dpyinfo->Xatom_net_wm_state_maximized_horz,
8483 dpyinfo->Xatom_net_wm_state_maximized_vert);
8484 break;
8485 case FULLSCREEN_NONE:
8486 if (cur == FULLSCREEN_BOTH)
8487 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_fullscreen, None);
8488 else
8489 set_wm_state (frame, 0, dpyinfo->Xatom_net_wm_state_maximized_horz,
8490 dpyinfo->Xatom_net_wm_state_maximized_vert);
8491 }
8492
8493 f->want_fullscreen = FULLSCREEN_NONE;
8494
8495 }
8496
8497 return have_net_atom;
8498 }
8499
8500 static void
8501 XTfullscreen_hook (struct frame *f)
8502 {
8503 if (FRAME_VISIBLE_P (f))
8504 {
8505 block_input ();
8506 x_check_fullscreen (f);
8507 x_sync (f);
8508 unblock_input ();
8509 }
8510 }
8511
8512
8513 static int
8514 x_handle_net_wm_state (struct frame *f, XPropertyEvent *event)
8515 {
8516 int value = FULLSCREEN_NONE;
8517 Lisp_Object lval;
8518 int sticky = 0;
8519 int not_hidden = get_current_wm_state (f, event->window, &value, &sticky);
8520
8521 lval = Qnil;
8522 switch (value)
8523 {
8524 case FULLSCREEN_WIDTH:
8525 lval = Qfullwidth;
8526 break;
8527 case FULLSCREEN_HEIGHT:
8528 lval = Qfullheight;
8529 break;
8530 case FULLSCREEN_BOTH:
8531 lval = Qfullboth;
8532 break;
8533 case FULLSCREEN_MAXIMIZED:
8534 lval = Qmaximized;
8535 break;
8536 }
8537
8538 store_frame_param (f, Qfullscreen, lval);
8539 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
8540
8541 return not_hidden;
8542 }
8543
8544 /* Check if we need to resize the frame due to a fullscreen request.
8545 If so needed, resize the frame. */
8546 static void
8547 x_check_fullscreen (struct frame *f)
8548 {
8549 if (do_ewmh_fullscreen (f))
8550 return;
8551
8552 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
8553 return; /* Only fullscreen without WM or with EWM hints (above). */
8554
8555 /* Setting fullscreen to nil doesn't do anything. We could save the
8556 last non-fullscreen size and restore it, but it seems like a
8557 lot of work for this unusual case (no window manager running). */
8558
8559 if (f->want_fullscreen != FULLSCREEN_NONE)
8560 {
8561 int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
8562 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8563
8564 switch (f->want_fullscreen)
8565 {
8566 /* No difference between these two when there is no WM */
8567 case FULLSCREEN_BOTH:
8568 case FULLSCREEN_MAXIMIZED:
8569 width = x_display_pixel_width (dpyinfo);
8570 height = x_display_pixel_height (dpyinfo);
8571 break;
8572 case FULLSCREEN_WIDTH:
8573 width = x_display_pixel_width (dpyinfo);
8574 break;
8575 case FULLSCREEN_HEIGHT:
8576 height = x_display_pixel_height (dpyinfo);
8577 }
8578
8579 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8580 width, height);
8581 }
8582 }
8583
8584 /* This function is called by x_set_offset to determine whether the window
8585 manager interfered with the positioning of the frame. Type A window
8586 managers position the surrounding window manager decorations a small
8587 amount above and left of the user-supplied position. Type B window
8588 managers position the surrounding window manager decorations at the
8589 user-specified position. If we detect a Type A window manager, we
8590 compensate by moving the window right and down by the proper amount. */
8591
8592 static void
8593 x_check_expected_move (struct frame *f, int expected_left, int expected_top)
8594 {
8595 int current_left = 0, current_top = 0;
8596
8597 /* x_real_positions returns the left and top offsets of the outermost
8598 window manager window around the frame. */
8599
8600 x_real_positions (f, &current_left, &current_top);
8601
8602 if (current_left != expected_left || current_top != expected_top)
8603 {
8604 /* It's a "Type A" window manager. */
8605
8606 int adjusted_left;
8607 int adjusted_top;
8608
8609 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8610 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
8611 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
8612
8613 /* Now fix the mispositioned frame's location. */
8614
8615 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
8616 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
8617
8618 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8619 adjusted_left, adjusted_top);
8620
8621 x_sync_with_move (f, expected_left, expected_top, 0);
8622 }
8623 else
8624 /* It's a "Type B" window manager. We don't have to adjust the
8625 frame's position. */
8626
8627 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8628 }
8629
8630
8631 /* Wait for XGetGeometry to return up-to-date position information for a
8632 recently-moved frame. Call this immediately after calling XMoveWindow.
8633 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8634 frame has been moved to, so we use a fuzzy position comparison instead
8635 of an exact comparison. */
8636
8637 static void
8638 x_sync_with_move (struct frame *f, int left, int top, int fuzzy)
8639 {
8640 int count = 0;
8641
8642 while (count++ < 50)
8643 {
8644 int current_left = 0, current_top = 0;
8645
8646 /* In theory, this call to XSync only needs to happen once, but in
8647 practice, it doesn't seem to work, hence the need for the surrounding
8648 loop. */
8649
8650 XSync (FRAME_X_DISPLAY (f), False);
8651 x_real_positions (f, &current_left, &current_top);
8652
8653 if (fuzzy)
8654 {
8655 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8656 pixels. */
8657
8658 if (eabs (current_left - left) <= 10
8659 && eabs (current_top - top) <= 40)
8660 return;
8661 }
8662 else if (current_left == left && current_top == top)
8663 return;
8664 }
8665
8666 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8667 will then return up-to-date position info. */
8668
8669 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8670 }
8671
8672
8673 /* Wait for an event on frame F matching EVENTTYPE. */
8674 void
8675 x_wait_for_event (struct frame *f, int eventtype)
8676 {
8677 int level = interrupt_input_blocked;
8678
8679 SELECT_TYPE fds;
8680 EMACS_TIME tmo, tmo_at, time_now;
8681 int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
8682
8683 pending_event_wait.f = f;
8684 pending_event_wait.eventtype = eventtype;
8685
8686 /* Set timeout to 0.1 second. Hopefully not noticeable.
8687 Maybe it should be configurable. */
8688 tmo = make_emacs_time (0, 100 * 1000 * 1000);
8689 tmo_at = add_emacs_time (current_emacs_time (), tmo);
8690
8691 while (pending_event_wait.eventtype)
8692 {
8693 pending_signals = 1;
8694 totally_unblock_input ();
8695 /* XTread_socket is called after unblock. */
8696 block_input ();
8697 interrupt_input_blocked = level;
8698
8699 FD_ZERO (&fds);
8700 FD_SET (fd, &fds);
8701
8702 time_now = current_emacs_time ();
8703 if (EMACS_TIME_LT (tmo_at, time_now))
8704 break;
8705
8706 tmo = sub_emacs_time (tmo_at, time_now);
8707 if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
8708 break; /* Timeout */
8709 }
8710 pending_event_wait.f = 0;
8711 pending_event_wait.eventtype = 0;
8712 }
8713
8714
8715 /* Change the size of frame F's X window to COLS/ROWS in the case F
8716 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8717 top-left-corner window gravity for this size change and subsequent
8718 size changes. Otherwise we leave the window gravity unchanged. */
8719
8720 static void
8721 x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
8722 {
8723 int pixelwidth, pixelheight;
8724
8725 check_frame_size (f, &rows, &cols);
8726 f->scroll_bar_actual_width
8727 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8728 ? 0
8729 : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
8730
8731 compute_fringe_widths (f, 0);
8732
8733 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
8734 + FRAME_TOOLBAR_WIDTH (f);
8735 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
8736 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
8737
8738 if (change_gravity) f->win_gravity = NorthWestGravity;
8739 x_wm_set_size_hint (f, (long) 0, 0);
8740 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8741 pixelwidth, pixelheight);
8742
8743
8744 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8745 receive in the ConfigureNotify event; if we get what we asked
8746 for, then the event won't cause the screen to become garbaged, so
8747 we have to make sure to do it here. */
8748 SET_FRAME_GARBAGED (f);
8749
8750 /* Now, strictly speaking, we can't be sure that this is accurate,
8751 but the window manager will get around to dealing with the size
8752 change request eventually, and we'll hear how it went when the
8753 ConfigureNotify event gets here.
8754
8755 We could just not bother storing any of this information here,
8756 and let the ConfigureNotify event set everything up, but that
8757 might be kind of confusing to the Lisp code, since size changes
8758 wouldn't be reported in the frame parameters until some random
8759 point in the future when the ConfigureNotify event arrives.
8760
8761 We pass 1 for DELAY since we can't run Lisp code inside of
8762 a BLOCK_INPUT. */
8763
8764 /* But the ConfigureNotify may in fact never arrive, and then this is
8765 not right if the frame is visible. Instead wait (with timeout)
8766 for the ConfigureNotify. */
8767 if (FRAME_VISIBLE_P (f))
8768 x_wait_for_event (f, ConfigureNotify);
8769 else
8770 {
8771 change_frame_size (f, rows, cols, 0, 1, 0);
8772 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8773 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8774 x_sync (f);
8775 }
8776 }
8777
8778
8779 /* Call this to change the size of frame F's x-window.
8780 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8781 for this size change and subsequent size changes.
8782 Otherwise we leave the window gravity unchanged. */
8783
8784 void
8785 x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
8786 {
8787 block_input ();
8788
8789 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8790 {
8791 int r, c;
8792
8793 /* When the frame is maximized/fullscreen or running under for
8794 example Xmonad, x_set_window_size_1 will be a no-op.
8795 In that case, the right thing to do is extend rows/cols to
8796 the current frame size. We do that first if x_set_window_size_1
8797 turns out to not be a no-op (there is no way to know).
8798 The size will be adjusted again if the frame gets a
8799 ConfigureNotify event as a result of x_set_window_size. */
8800 int pixelh = FRAME_PIXEL_HEIGHT (f);
8801 #ifdef USE_X_TOOLKIT
8802 /* The menu bar is not part of text lines. The tool bar
8803 is however. */
8804 pixelh -= FRAME_MENUBAR_HEIGHT (f);
8805 #endif
8806 r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
8807 /* Update f->scroll_bar_actual_width because it is used in
8808 FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
8809 f->scroll_bar_actual_width
8810 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
8811 c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
8812 change_frame_size (f, r, c, 0, 1, 0);
8813 }
8814
8815 #ifdef USE_GTK
8816 if (FRAME_GTK_WIDGET (f))
8817 xg_frame_set_char_size (f, cols, rows);
8818 else
8819 x_set_window_size_1 (f, change_gravity, cols, rows);
8820 #else /* not USE_GTK */
8821
8822 x_set_window_size_1 (f, change_gravity, cols, rows);
8823
8824 #endif /* not USE_GTK */
8825
8826 /* If cursor was outside the new size, mark it as off. */
8827 mark_window_cursors_off (XWINDOW (f->root_window));
8828
8829 /* Clear out any recollection of where the mouse highlighting was,
8830 since it might be in a place that's outside the new frame size.
8831 Actually checking whether it is outside is a pain in the neck,
8832 so don't try--just let the highlighting be done afresh with new size. */
8833 cancel_mouse_face (f);
8834
8835 unblock_input ();
8836 }
8837 \f
8838 /* Mouse warping. */
8839
8840 void
8841 x_set_mouse_position (struct frame *f, int x, int y)
8842 {
8843 int pix_x, pix_y;
8844
8845 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
8846 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
8847
8848 if (pix_x < 0) pix_x = 0;
8849 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
8850
8851 if (pix_y < 0) pix_y = 0;
8852 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
8853
8854 block_input ();
8855
8856 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8857 0, 0, 0, 0, pix_x, pix_y);
8858 unblock_input ();
8859 }
8860
8861 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8862
8863 void
8864 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
8865 {
8866 block_input ();
8867
8868 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8869 0, 0, 0, 0, pix_x, pix_y);
8870 unblock_input ();
8871 }
8872 \f
8873 /* Raise frame F. */
8874
8875 void
8876 x_raise_frame (struct frame *f)
8877 {
8878 block_input ();
8879 if (FRAME_VISIBLE_P (f))
8880 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8881 XFlush (FRAME_X_DISPLAY (f));
8882 unblock_input ();
8883 }
8884
8885 /* Lower frame F. */
8886
8887 static void
8888 x_lower_frame (struct frame *f)
8889 {
8890 if (FRAME_VISIBLE_P (f))
8891 {
8892 block_input ();
8893 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8894 XFlush (FRAME_X_DISPLAY (f));
8895 unblock_input ();
8896 }
8897 }
8898
8899 /* Request focus with XEmbed */
8900
8901 void
8902 xembed_request_focus (struct frame *f)
8903 {
8904 /* See XEmbed Protocol Specification at
8905 http://freedesktop.org/wiki/Specifications/xembed-spec */
8906 if (FRAME_VISIBLE_P (f))
8907 xembed_send_message (f, CurrentTime,
8908 XEMBED_REQUEST_FOCUS, 0, 0, 0);
8909 }
8910
8911 /* Activate frame with Extended Window Manager Hints */
8912
8913 void
8914 x_ewmh_activate_frame (struct frame *f)
8915 {
8916 /* See Window Manager Specification/Extended Window Manager Hints at
8917 http://freedesktop.org/wiki/Specifications/wm-spec */
8918
8919 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8920
8921 if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window))
8922 {
8923 Lisp_Object frame;
8924 XSETFRAME (frame, f);
8925 x_send_client_event (frame, make_number (0), frame,
8926 dpyinfo->Xatom_net_active_window,
8927 make_number (32), list2i (1, last_user_time));
8928 }
8929 }
8930
8931 static void
8932 XTframe_raise_lower (struct frame *f, int raise_flag)
8933 {
8934 if (raise_flag)
8935 x_raise_frame (f);
8936 else
8937 x_lower_frame (f);
8938 }
8939 \f
8940 /* XEmbed implementation. */
8941
8942 #if defined USE_X_TOOLKIT || ! defined USE_GTK
8943
8944 /* XEmbed implementation. */
8945
8946 #define XEMBED_VERSION 0
8947
8948 static void
8949 xembed_set_info (struct frame *f, enum xembed_info flags)
8950 {
8951 unsigned long data[2];
8952 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8953
8954 data[0] = XEMBED_VERSION;
8955 data[1] = flags;
8956
8957 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8958 dpyinfo->Xatom_XEMBED_INFO, dpyinfo->Xatom_XEMBED_INFO,
8959 32, PropModeReplace, (unsigned char *) data, 2);
8960 }
8961 #endif /* defined USE_X_TOOLKIT || ! defined USE_GTK */
8962
8963 static void
8964 xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
8965 long int detail, long int data1, long int data2)
8966 {
8967 XEvent event;
8968
8969 event.xclient.type = ClientMessage;
8970 event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
8971 event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
8972 event.xclient.format = 32;
8973 event.xclient.data.l[0] = t;
8974 event.xclient.data.l[1] = msg;
8975 event.xclient.data.l[2] = detail;
8976 event.xclient.data.l[3] = data1;
8977 event.xclient.data.l[4] = data2;
8978
8979 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
8980 False, NoEventMask, &event);
8981 XSync (FRAME_X_DISPLAY (f), False);
8982 }
8983 \f
8984 /* Change of visibility. */
8985
8986 /* This tries to wait until the frame is really visible.
8987 However, if the window manager asks the user where to position
8988 the frame, this will return before the user finishes doing that.
8989 The frame will not actually be visible at that time,
8990 but it will become visible later when the window manager
8991 finishes with it. */
8992
8993 void
8994 x_make_frame_visible (struct frame *f)
8995 {
8996 Lisp_Object type;
8997 int original_top, original_left;
8998 int retry_count = 2;
8999
9000 retry:
9001
9002 block_input ();
9003
9004 type = x_icon_type (f);
9005 if (!NILP (type))
9006 x_bitmap_icon (f, type);
9007
9008 if (! FRAME_VISIBLE_P (f))
9009 {
9010 /* We test FRAME_GARBAGED_P here to make sure we don't
9011 call x_set_offset a second time
9012 if we get to x_make_frame_visible a second time
9013 before the window gets really visible. */
9014 if (! FRAME_ICONIFIED_P (f)
9015 && ! FRAME_X_EMBEDDED_P (f)
9016 && ! f->output_data.x->asked_for_visible)
9017 x_set_offset (f, f->left_pos, f->top_pos, 0);
9018
9019 f->output_data.x->asked_for_visible = 1;
9020
9021 if (! EQ (Vx_no_window_manager, Qt))
9022 x_wm_set_window_state (f, NormalState);
9023 #ifdef USE_X_TOOLKIT
9024 if (FRAME_X_EMBEDDED_P (f))
9025 xembed_set_info (f, XEMBED_MAPPED);
9026 else
9027 {
9028 /* This was XtPopup, but that did nothing for an iconified frame. */
9029 XtMapWidget (f->output_data.x->widget);
9030 }
9031 #else /* not USE_X_TOOLKIT */
9032 #ifdef USE_GTK
9033 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9034 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9035 #else
9036 if (FRAME_X_EMBEDDED_P (f))
9037 xembed_set_info (f, XEMBED_MAPPED);
9038 else
9039 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9040 #endif /* not USE_GTK */
9041 #endif /* not USE_X_TOOLKIT */
9042 }
9043
9044 XFlush (FRAME_X_DISPLAY (f));
9045
9046 /* Synchronize to ensure Emacs knows the frame is visible
9047 before we do anything else. We do this loop with input not blocked
9048 so that incoming events are handled. */
9049 {
9050 Lisp_Object frame;
9051 int count;
9052 /* This must be before UNBLOCK_INPUT
9053 since events that arrive in response to the actions above
9054 will set it when they are handled. */
9055 int previously_visible = f->output_data.x->has_been_visible;
9056
9057 original_left = f->left_pos;
9058 original_top = f->top_pos;
9059
9060 /* This must come after we set COUNT. */
9061 unblock_input ();
9062
9063 /* We unblock here so that arriving X events are processed. */
9064
9065 /* Now move the window back to where it was "supposed to be".
9066 But don't do it if the gravity is negative.
9067 When the gravity is negative, this uses a position
9068 that is 3 pixels too low. Perhaps that's really the border width.
9069
9070 Don't do this if the window has never been visible before,
9071 because the window manager may choose the position
9072 and we don't want to override it. */
9073
9074 if (! FRAME_VISIBLE_P (f)
9075 && ! FRAME_ICONIFIED_P (f)
9076 && ! FRAME_X_EMBEDDED_P (f)
9077 && f->win_gravity == NorthWestGravity
9078 && previously_visible)
9079 {
9080 Drawable rootw;
9081 int x, y;
9082 unsigned int width, height, border, depth;
9083
9084 block_input ();
9085
9086 /* On some window managers (such as FVWM) moving an existing
9087 window, even to the same place, causes the window manager
9088 to introduce an offset. This can cause the window to move
9089 to an unexpected location. Check the geometry (a little
9090 slow here) and then verify that the window is in the right
9091 place. If the window is not in the right place, move it
9092 there, and take the potential window manager hit. */
9093 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9094 &rootw, &x, &y, &width, &height, &border, &depth);
9095
9096 if (original_left != x || original_top != y)
9097 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9098 original_left, original_top);
9099
9100 unblock_input ();
9101 }
9102
9103 XSETFRAME (frame, f);
9104
9105 /* Wait until the frame is visible. Process X events until a
9106 MapNotify event has been seen, or until we think we won't get a
9107 MapNotify at all.. */
9108 for (count = input_signal_count + 10;
9109 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9110 {
9111 /* Force processing of queued events. */
9112 x_sync (f);
9113
9114 /* Machines that do polling rather than SIGIO have been
9115 observed to go into a busy-wait here. So we'll fake an
9116 alarm signal to let the handler know that there's something
9117 to be read. We used to raise a real alarm, but it seems
9118 that the handler isn't always enabled here. This is
9119 probably a bug. */
9120 if (input_polling_used ())
9121 {
9122 /* It could be confusing if a real alarm arrives while
9123 processing the fake one. Turn it off and let the
9124 handler reset it. */
9125 int old_poll_suppress_count = poll_suppress_count;
9126 poll_suppress_count = 1;
9127 poll_for_input_1 ();
9128 poll_suppress_count = old_poll_suppress_count;
9129 }
9130 }
9131
9132 /* 2000-09-28: In
9133
9134 (let ((f (selected-frame)))
9135 (iconify-frame f)
9136 (raise-frame f))
9137
9138 the frame is not raised with various window managers on
9139 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
9140 unknown reason, the call to XtMapWidget is completely ignored.
9141 Mapping the widget a second time works. */
9142
9143 if (!FRAME_VISIBLE_P (f) && --retry_count != 0)
9144 goto retry;
9145 }
9146 }
9147
9148 /* Change from mapped state to withdrawn state. */
9149
9150 /* Make the frame visible (mapped and not iconified). */
9151
9152 void
9153 x_make_frame_invisible (struct frame *f)
9154 {
9155 Window window;
9156
9157 /* Use the frame's outermost window, not the one we normally draw on. */
9158 window = FRAME_OUTER_WINDOW (f);
9159
9160 /* Don't keep the highlight on an invisible frame. */
9161 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9162 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9163
9164 block_input ();
9165
9166 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
9167 that the current position of the window is user-specified, rather than
9168 program-specified, so that when the window is mapped again, it will be
9169 placed at the same location, without forcing the user to position it
9170 by hand again (they have already done that once for this window.) */
9171 x_wm_set_size_hint (f, (long) 0, 1);
9172
9173 #ifdef USE_GTK
9174 if (FRAME_GTK_OUTER_WIDGET (f))
9175 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
9176 else
9177 #else
9178 if (FRAME_X_EMBEDDED_P (f))
9179 xembed_set_info (f, 0);
9180 else
9181 #endif
9182 {
9183
9184 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
9185 DefaultScreen (FRAME_X_DISPLAY (f))))
9186 {
9187 unblock_input ();
9188 error ("Can't notify window manager of window withdrawal");
9189 }
9190 }
9191
9192 /* We can't distinguish this from iconification
9193 just by the event that we get from the server.
9194 So we can't win using the usual strategy of letting
9195 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9196 and synchronize with the server to make sure we agree. */
9197 SET_FRAME_VISIBLE (f, 0);
9198 SET_FRAME_ICONIFIED (f, 0);
9199
9200 x_sync (f);
9201
9202 unblock_input ();
9203 }
9204
9205 /* Change window state from mapped to iconified. */
9206
9207 void
9208 x_iconify_frame (struct frame *f)
9209 {
9210 #ifdef USE_X_TOOLKIT
9211 int result;
9212 #endif
9213 Lisp_Object type;
9214
9215 /* Don't keep the highlight on an invisible frame. */
9216 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
9217 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9218
9219 if (FRAME_ICONIFIED_P (f))
9220 return;
9221
9222 block_input ();
9223
9224 type = x_icon_type (f);
9225 if (!NILP (type))
9226 x_bitmap_icon (f, type);
9227
9228 #if defined (USE_GTK)
9229 if (FRAME_GTK_OUTER_WIDGET (f))
9230 {
9231 if (! FRAME_VISIBLE_P (f))
9232 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
9233
9234 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
9235 SET_FRAME_VISIBLE (f, 0);
9236 SET_FRAME_ICONIFIED (f, 1);
9237 unblock_input ();
9238 return;
9239 }
9240 #endif
9241
9242 #ifdef USE_X_TOOLKIT
9243
9244 if (! FRAME_VISIBLE_P (f))
9245 {
9246 if (! EQ (Vx_no_window_manager, Qt))
9247 x_wm_set_window_state (f, IconicState);
9248 /* This was XtPopup, but that did nothing for an iconified frame. */
9249 XtMapWidget (f->output_data.x->widget);
9250 /* The server won't give us any event to indicate
9251 that an invisible frame was changed to an icon,
9252 so we have to record it here. */
9253 SET_FRAME_VISIBLE (f, 0);
9254 SET_FRAME_ICONIFIED (f, 1);
9255 unblock_input ();
9256 return;
9257 }
9258
9259 result = XIconifyWindow (FRAME_X_DISPLAY (f),
9260 XtWindow (f->output_data.x->widget),
9261 DefaultScreen (FRAME_X_DISPLAY (f)));
9262 unblock_input ();
9263
9264 if (!result)
9265 error ("Can't notify window manager of iconification");
9266
9267 SET_FRAME_ICONIFIED (f, 1);
9268 SET_FRAME_VISIBLE (f, 0);
9269
9270 block_input ();
9271 XFlush (FRAME_X_DISPLAY (f));
9272 unblock_input ();
9273 #else /* not USE_X_TOOLKIT */
9274
9275 /* Make sure the X server knows where the window should be positioned,
9276 in case the user deiconifies with the window manager. */
9277 if (! FRAME_VISIBLE_P (f)
9278 && ! FRAME_ICONIFIED_P (f)
9279 && ! FRAME_X_EMBEDDED_P (f))
9280 x_set_offset (f, f->left_pos, f->top_pos, 0);
9281
9282 /* Since we don't know which revision of X we're running, we'll use both
9283 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
9284
9285 /* X11R4: send a ClientMessage to the window manager using the
9286 WM_CHANGE_STATE type. */
9287 {
9288 XEvent msg;
9289
9290 msg.xclient.window = FRAME_X_WINDOW (f);
9291 msg.xclient.type = ClientMessage;
9292 msg.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
9293 msg.xclient.format = 32;
9294 msg.xclient.data.l[0] = IconicState;
9295
9296 if (! XSendEvent (FRAME_X_DISPLAY (f),
9297 DefaultRootWindow (FRAME_X_DISPLAY (f)),
9298 False,
9299 SubstructureRedirectMask | SubstructureNotifyMask,
9300 &msg))
9301 {
9302 unblock_input ();
9303 error ("Can't notify window manager of iconification");
9304 }
9305 }
9306
9307 /* X11R3: set the initial_state field of the window manager hints to
9308 IconicState. */
9309 x_wm_set_window_state (f, IconicState);
9310
9311 if (!FRAME_VISIBLE_P (f))
9312 {
9313 /* If the frame was withdrawn, before, we must map it. */
9314 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9315 }
9316
9317 SET_FRAME_ICONIFIED (f, 1);
9318 SET_FRAME_VISIBLE (f, 0);
9319
9320 XFlush (FRAME_X_DISPLAY (f));
9321 unblock_input ();
9322 #endif /* not USE_X_TOOLKIT */
9323 }
9324
9325 \f
9326 /* Free X resources of frame F. */
9327
9328 void
9329 x_free_frame_resources (struct frame *f)
9330 {
9331 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9332 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
9333 #ifdef USE_X_TOOLKIT
9334 Lisp_Object bar;
9335 struct scroll_bar *b;
9336 #endif
9337
9338 block_input ();
9339
9340 /* If a display connection is dead, don't try sending more
9341 commands to the X server. */
9342 if (dpyinfo->display)
9343 {
9344 /* We must free faces before destroying windows because some
9345 font-driver (e.g. xft) access a window while finishing a
9346 face. */
9347 if (FRAME_FACE_CACHE (f))
9348 free_frame_faces (f);
9349
9350 if (f->output_data.x->icon_desc)
9351 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
9352
9353 #ifdef USE_X_TOOLKIT
9354 /* Explicitly destroy the scroll bars of the frame. Without
9355 this, we get "BadDrawable" errors from the toolkit later on,
9356 presumably from expose events generated for the disappearing
9357 toolkit scroll bars. */
9358 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
9359 {
9360 b = XSCROLL_BAR (bar);
9361 x_scroll_bar_remove (b);
9362 }
9363 #endif
9364
9365 #ifdef HAVE_X_I18N
9366 if (FRAME_XIC (f))
9367 free_frame_xic (f);
9368 #endif
9369
9370 #ifdef USE_X_TOOLKIT
9371 if (f->output_data.x->widget)
9372 {
9373 XtDestroyWidget (f->output_data.x->widget);
9374 f->output_data.x->widget = NULL;
9375 }
9376 /* Tooltips don't have widgets, only a simple X window, even if
9377 we are using a toolkit. */
9378 else if (FRAME_X_WINDOW (f))
9379 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9380
9381 free_frame_menubar (f);
9382 #else /* !USE_X_TOOLKIT */
9383
9384 #ifdef USE_GTK
9385 xg_free_frame_widgets (f);
9386 #endif /* USE_GTK */
9387
9388 if (FRAME_X_WINDOW (f))
9389 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9390 #endif /* !USE_X_TOOLKIT */
9391
9392 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
9393 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
9394 unload_color (f, f->output_data.x->cursor_pixel);
9395 unload_color (f, f->output_data.x->cursor_foreground_pixel);
9396 unload_color (f, f->output_data.x->border_pixel);
9397 unload_color (f, f->output_data.x->mouse_pixel);
9398
9399 if (f->output_data.x->scroll_bar_background_pixel != -1)
9400 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
9401 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9402 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
9403 #ifdef USE_TOOLKIT_SCROLL_BARS
9404 /* Scrollbar shadow colors. */
9405 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
9406 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
9407 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
9408 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
9409 #endif /* USE_TOOLKIT_SCROLL_BARS */
9410 if (f->output_data.x->white_relief.allocated_p)
9411 unload_color (f, f->output_data.x->white_relief.pixel);
9412 if (f->output_data.x->black_relief.allocated_p)
9413 unload_color (f, f->output_data.x->black_relief.pixel);
9414
9415 x_free_gcs (f);
9416
9417 /* Free extra GCs allocated by x_setup_relief_colors. */
9418 if (f->output_data.x->white_relief.gc)
9419 {
9420 XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
9421 f->output_data.x->white_relief.gc = 0;
9422 }
9423 if (f->output_data.x->black_relief.gc)
9424 {
9425 XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
9426 f->output_data.x->black_relief.gc = 0;
9427 }
9428
9429 XFlush (FRAME_X_DISPLAY (f));
9430 }
9431
9432 xfree (f->output_data.x->saved_menu_event);
9433 xfree (f->output_data.x);
9434 f->output_data.x = NULL;
9435
9436 if (f == dpyinfo->x_focus_frame)
9437 dpyinfo->x_focus_frame = 0;
9438 if (f == dpyinfo->x_focus_event_frame)
9439 dpyinfo->x_focus_event_frame = 0;
9440 if (f == dpyinfo->x_highlight_frame)
9441 dpyinfo->x_highlight_frame = 0;
9442 if (f == hlinfo->mouse_face_mouse_frame)
9443 reset_mouse_highlight (hlinfo);
9444
9445 unblock_input ();
9446 }
9447
9448
9449 /* Destroy the X window of frame F. */
9450
9451 static void
9452 x_destroy_window (struct frame *f)
9453 {
9454 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9455
9456 /* If a display connection is dead, don't try sending more
9457 commands to the X server. */
9458 if (dpyinfo->display != 0)
9459 x_free_frame_resources (f);
9460
9461 dpyinfo->reference_count--;
9462 }
9463
9464 \f
9465 /* Setting window manager hints. */
9466
9467 /* Set the normal size hints for the window manager, for frame F.
9468 FLAGS is the flags word to use--or 0 meaning preserve the flags
9469 that the window now has.
9470 If USER_POSITION, set the USPosition
9471 flag (this is useful when FLAGS is 0).
9472 The GTK version is in gtkutils.c. */
9473
9474 #ifndef USE_GTK
9475 void
9476 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
9477 {
9478 XSizeHints size_hints;
9479 Window window = FRAME_OUTER_WINDOW (f);
9480
9481 #ifdef USE_X_TOOLKIT
9482 if (f->output_data.x->widget)
9483 {
9484 widget_update_wm_size_hints (f->output_data.x->widget);
9485 return;
9486 }
9487 #endif
9488
9489 /* Setting PMaxSize caused various problems. */
9490 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9491
9492 size_hints.x = f->left_pos;
9493 size_hints.y = f->top_pos;
9494
9495 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9496 size_hints.width = FRAME_PIXEL_WIDTH (f);
9497
9498 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9499 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9500 size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
9501 - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9502 size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
9503 - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9504
9505 /* Calculate the base and minimum sizes. */
9506 {
9507 int base_width, base_height;
9508 int min_rows = 0, min_cols = 0;
9509
9510 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9511 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9512
9513 check_frame_size (f, &min_rows, &min_cols);
9514
9515 /* The window manager uses the base width hints to calculate the
9516 current number of rows and columns in the frame while
9517 resizing; min_width and min_height aren't useful for this
9518 purpose, since they might not give the dimensions for a
9519 zero-row, zero-column frame.
9520
9521 We use the base_width and base_height members if we have
9522 them; otherwise, we set the min_width and min_height members
9523 to the size for a zero x zero frame. */
9524
9525 size_hints.flags |= PBaseSize;
9526 size_hints.base_width = base_width;
9527 size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
9528 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9529 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9530 }
9531
9532 /* If we don't need the old flags, we don't need the old hint at all. */
9533 if (flags)
9534 {
9535 size_hints.flags |= flags;
9536 goto no_read;
9537 }
9538
9539 {
9540 XSizeHints hints; /* Sometimes I hate X Windows... */
9541 long supplied_return;
9542 int value;
9543
9544 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9545 &supplied_return);
9546
9547 if (flags)
9548 size_hints.flags |= flags;
9549 else
9550 {
9551 if (value == 0)
9552 hints.flags = 0;
9553 if (hints.flags & PSize)
9554 size_hints.flags |= PSize;
9555 if (hints.flags & PPosition)
9556 size_hints.flags |= PPosition;
9557 if (hints.flags & USPosition)
9558 size_hints.flags |= USPosition;
9559 if (hints.flags & USSize)
9560 size_hints.flags |= USSize;
9561 }
9562 }
9563
9564 no_read:
9565
9566 #ifdef PWinGravity
9567 size_hints.win_gravity = f->win_gravity;
9568 size_hints.flags |= PWinGravity;
9569
9570 if (user_position)
9571 {
9572 size_hints.flags &= ~ PPosition;
9573 size_hints.flags |= USPosition;
9574 }
9575 #endif /* PWinGravity */
9576
9577 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9578 }
9579 #endif /* not USE_GTK */
9580
9581 /* Used for IconicState or NormalState */
9582
9583 static void
9584 x_wm_set_window_state (struct frame *f, int state)
9585 {
9586 #ifdef USE_X_TOOLKIT
9587 Arg al[1];
9588
9589 XtSetArg (al[0], XtNinitialState, state);
9590 XtSetValues (f->output_data.x->widget, al, 1);
9591 #else /* not USE_X_TOOLKIT */
9592 Window window = FRAME_X_WINDOW (f);
9593
9594 f->output_data.x->wm_hints.flags |= StateHint;
9595 f->output_data.x->wm_hints.initial_state = state;
9596
9597 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9598 #endif /* not USE_X_TOOLKIT */
9599 }
9600
9601 static void
9602 x_wm_set_icon_pixmap (struct frame *f, ptrdiff_t pixmap_id)
9603 {
9604 Pixmap icon_pixmap, icon_mask;
9605
9606 #if !defined USE_X_TOOLKIT && !defined USE_GTK
9607 Window window = FRAME_OUTER_WINDOW (f);
9608 #endif
9609
9610 if (pixmap_id > 0)
9611 {
9612 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
9613 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
9614 icon_mask = x_bitmap_mask (f, pixmap_id);
9615 f->output_data.x->wm_hints.icon_mask = icon_mask;
9616 }
9617 else
9618 {
9619 /* It seems there is no way to turn off use of an icon
9620 pixmap. */
9621 return;
9622 }
9623
9624
9625 #ifdef USE_GTK
9626 {
9627 xg_set_frame_icon (f, icon_pixmap, icon_mask);
9628 return;
9629 }
9630
9631 #elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
9632
9633 {
9634 Arg al[1];
9635 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
9636 XtSetValues (f->output_data.x->widget, al, 1);
9637 XtSetArg (al[0], XtNiconMask, icon_mask);
9638 XtSetValues (f->output_data.x->widget, al, 1);
9639 }
9640
9641 #else /* not USE_X_TOOLKIT && not USE_GTK */
9642
9643 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
9644 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9645
9646 #endif /* not USE_X_TOOLKIT && not USE_GTK */
9647 }
9648
9649 void
9650 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
9651 {
9652 Window window = FRAME_OUTER_WINDOW (f);
9653
9654 f->output_data.x->wm_hints.flags |= IconPositionHint;
9655 f->output_data.x->wm_hints.icon_x = icon_x;
9656 f->output_data.x->wm_hints.icon_y = icon_y;
9657
9658 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9659 }
9660
9661 \f
9662 /***********************************************************************
9663 Fonts
9664 ***********************************************************************/
9665
9666 #ifdef GLYPH_DEBUG
9667
9668 /* Check that FONT is valid on frame F. It is if it can be found in F's
9669 font table. */
9670
9671 static void
9672 x_check_font (struct frame *f, struct font *font)
9673 {
9674 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
9675 if (font->driver->check)
9676 eassert (font->driver->check (f, font) == 0);
9677 }
9678
9679 #endif /* GLYPH_DEBUG */
9680
9681 \f
9682 /***********************************************************************
9683 Initialization
9684 ***********************************************************************/
9685
9686 #ifdef USE_X_TOOLKIT
9687 static XrmOptionDescRec emacs_options[] = {
9688 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
9689 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
9690
9691 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
9692 XrmoptionSepArg, NULL},
9693 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
9694
9695 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9696 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9697 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
9698 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9699 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
9700 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
9701 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
9702 };
9703
9704 /* Whether atimer for Xt timeouts is activated or not. */
9705
9706 static int x_timeout_atimer_activated_flag;
9707
9708 #endif /* USE_X_TOOLKIT */
9709
9710 static int x_initialized;
9711
9712 /* Test whether two display-name strings agree up to the dot that separates
9713 the screen number from the server number. */
9714 static int
9715 same_x_server (const char *name1, const char *name2)
9716 {
9717 int seen_colon = 0;
9718 const char *system_name = SSDATA (Vsystem_name);
9719 ptrdiff_t system_name_length = SBYTES (Vsystem_name);
9720 ptrdiff_t length_until_period = 0;
9721
9722 while (system_name[length_until_period] != 0
9723 && system_name[length_until_period] != '.')
9724 length_until_period++;
9725
9726 /* Treat `unix' like an empty host name. */
9727 if (! strncmp (name1, "unix:", 5))
9728 name1 += 4;
9729 if (! strncmp (name2, "unix:", 5))
9730 name2 += 4;
9731 /* Treat this host's name like an empty host name. */
9732 if (! strncmp (name1, system_name, system_name_length)
9733 && name1[system_name_length] == ':')
9734 name1 += system_name_length;
9735 if (! strncmp (name2, system_name, system_name_length)
9736 && name2[system_name_length] == ':')
9737 name2 += system_name_length;
9738 /* Treat this host's domainless name like an empty host name. */
9739 if (! strncmp (name1, system_name, length_until_period)
9740 && name1[length_until_period] == ':')
9741 name1 += length_until_period;
9742 if (! strncmp (name2, system_name, length_until_period)
9743 && name2[length_until_period] == ':')
9744 name2 += length_until_period;
9745
9746 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
9747 {
9748 if (*name1 == ':')
9749 seen_colon = 1;
9750 if (seen_colon && *name1 == '.')
9751 return 1;
9752 }
9753 return (seen_colon
9754 && (*name1 == '.' || *name1 == '\0')
9755 && (*name2 == '.' || *name2 == '\0'));
9756 }
9757
9758 /* Count number of set bits in mask and number of bits to shift to
9759 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
9760 to 5. */
9761 static void
9762 get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
9763 {
9764 int nr = 0;
9765 int off = 0;
9766
9767 while (!(mask & 1))
9768 {
9769 off++;
9770 mask >>= 1;
9771 }
9772
9773 while (mask & 1)
9774 {
9775 nr++;
9776 mask >>= 1;
9777 }
9778
9779 *offset = off;
9780 *bits = nr;
9781 }
9782
9783 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
9784 But don't permanently open it, just test its availability. */
9785
9786 bool
9787 x_display_ok (const char *display)
9788 {
9789 Display *dpy = XOpenDisplay (display);
9790 return dpy ? (XCloseDisplay (dpy), 1) : 0;
9791 }
9792
9793 #ifdef USE_GTK
9794 static void
9795 my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
9796 const gchar *msg, gpointer user_data)
9797 {
9798 if (!strstr (msg, "g_set_prgname"))
9799 fprintf (stderr, "%s-WARNING **: %s\n", log_domain, msg);
9800 }
9801 #endif
9802
9803 /* Open a connection to X display DISPLAY_NAME, and return
9804 the structure that describes the open display.
9805 If we cannot contact the display, return null. */
9806
9807 struct x_display_info *
9808 x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
9809 {
9810 int connection;
9811 Display *dpy;
9812 struct terminal *terminal;
9813 struct x_display_info *dpyinfo;
9814 XrmDatabase xrdb;
9815 ptrdiff_t lim;
9816
9817 block_input ();
9818
9819 if (!x_initialized)
9820 {
9821 x_initialize ();
9822 ++x_initialized;
9823 }
9824
9825 if (! x_display_ok (SSDATA (display_name)))
9826 error ("Display %s can't be opened", SSDATA (display_name));
9827
9828 #ifdef USE_GTK
9829 {
9830 #define NUM_ARGV 10
9831 int argc;
9832 char *argv[NUM_ARGV];
9833 char **argv2 = argv;
9834 guint id;
9835
9836 if (x_initialized++ > 1)
9837 {
9838 xg_display_open (SSDATA (display_name), &dpy);
9839 }
9840 else
9841 {
9842 static char display_opt[] = "--display";
9843 static char name_opt[] = "--name";
9844
9845 for (argc = 0; argc < NUM_ARGV; ++argc)
9846 argv[argc] = 0;
9847
9848 argc = 0;
9849 argv[argc++] = initial_argv[0];
9850
9851 if (! NILP (display_name))
9852 {
9853 argv[argc++] = display_opt;
9854 argv[argc++] = SSDATA (display_name);
9855 }
9856
9857 argv[argc++] = name_opt;
9858 argv[argc++] = resource_name;
9859
9860 XSetLocaleModifiers ("");
9861
9862 /* Emacs can only handle core input events, so make sure
9863 Gtk doesn't use Xinput or Xinput2 extensions. */
9864 xputenv ("GDK_CORE_DEVICE_EVENTS=1");
9865
9866 /* Work around GLib bug that outputs a faulty warning. See
9867 https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
9868 id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
9869 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
9870
9871 /* NULL window -> events for all windows go to our function.
9872 Call before gtk_init so Gtk+ event filters comes after our. */
9873 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
9874
9875 /* gtk_init does set_locale. Fix locale before and after. */
9876 fixup_locale ();
9877 gtk_init (&argc, &argv2);
9878 fixup_locale ();
9879
9880 g_log_remove_handler ("GLib", id);
9881
9882 xg_initialize ();
9883
9884 dpy = DEFAULT_GDK_DISPLAY ();
9885
9886 #if ! GTK_CHECK_VERSION (2, 90, 0)
9887 /* Load our own gtkrc if it exists. */
9888 {
9889 const char *file = "~/.emacs.d/gtkrc";
9890 Lisp_Object s, abs_file;
9891
9892 s = build_string (file);
9893 abs_file = Fexpand_file_name (s, Qnil);
9894
9895 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
9896 gtk_rc_parse (SSDATA (abs_file));
9897 }
9898 #endif
9899
9900 XSetErrorHandler (x_error_handler);
9901 XSetIOErrorHandler (x_io_error_quitter);
9902 }
9903 }
9904 #else /* not USE_GTK */
9905 #ifdef USE_X_TOOLKIT
9906 /* weiner@footloose.sps.mot.com reports that this causes
9907 errors with X11R5:
9908 X protocol error: BadAtom (invalid Atom parameter)
9909 on protocol request 18skiloaf.
9910 So let's not use it until R6. */
9911 #ifdef HAVE_X11XTR6
9912 XtSetLanguageProc (NULL, NULL, NULL);
9913 #endif
9914
9915 {
9916 int argc = 0;
9917 char *argv[3];
9918
9919 argv[0] = "";
9920 argc = 1;
9921 if (xrm_option)
9922 {
9923 argv[argc++] = "-xrm";
9924 argv[argc++] = xrm_option;
9925 }
9926 turn_on_atimers (0);
9927 dpy = XtOpenDisplay (Xt_app_con, SSDATA (display_name),
9928 resource_name, EMACS_CLASS,
9929 emacs_options, XtNumber (emacs_options),
9930 &argc, argv);
9931 turn_on_atimers (1);
9932
9933 #ifdef HAVE_X11XTR6
9934 /* I think this is to compensate for XtSetLanguageProc. */
9935 fixup_locale ();
9936 #endif
9937 }
9938
9939 #else /* not USE_X_TOOLKIT */
9940 XSetLocaleModifiers ("");
9941 dpy = XOpenDisplay (SSDATA (display_name));
9942 #endif /* not USE_X_TOOLKIT */
9943 #endif /* not USE_GTK*/
9944
9945 /* Detect failure. */
9946 if (dpy == 0)
9947 {
9948 unblock_input ();
9949 return 0;
9950 }
9951
9952 /* We have definitely succeeded. Record the new connection. */
9953
9954 dpyinfo = xzalloc (sizeof *dpyinfo);
9955 terminal = x_create_terminal (dpyinfo);
9956
9957 {
9958 struct x_display_info *share;
9959 Lisp_Object tail;
9960
9961 for (share = x_display_list, tail = x_display_name_list; share;
9962 share = share->next, tail = XCDR (tail))
9963 if (same_x_server (SSDATA (XCAR (XCAR (tail))),
9964 SSDATA (display_name)))
9965 break;
9966 if (share)
9967 terminal->kboard = share->terminal->kboard;
9968 else
9969 {
9970 terminal->kboard = xmalloc (sizeof *terminal->kboard);
9971 init_kboard (terminal->kboard);
9972 kset_window_system (terminal->kboard, Qx);
9973
9974 /* Add the keyboard to the list before running Lisp code (via
9975 Qvendor_specific_keysyms below), since these are not traced
9976 via terminals but only through all_kboards. */
9977 terminal->kboard->next_kboard = all_kboards;
9978 all_kboards = terminal->kboard;
9979
9980 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
9981 {
9982 char *vendor = ServerVendor (dpy);
9983
9984 /* Protect terminal from GC before removing it from the
9985 list of terminals. */
9986 struct gcpro gcpro1;
9987 Lisp_Object gcpro_term;
9988 XSETTERMINAL (gcpro_term, terminal);
9989 GCPRO1 (gcpro_term);
9990
9991 /* Temporarily hide the partially initialized terminal. */
9992 terminal_list = terminal->next_terminal;
9993 unblock_input ();
9994 kset_system_key_alist
9995 (terminal->kboard,
9996 call1 (Qvendor_specific_keysyms,
9997 vendor ? build_string (vendor) : empty_unibyte_string));
9998 block_input ();
9999 terminal->next_terminal = terminal_list;
10000 terminal_list = terminal;
10001 UNGCPRO;
10002 }
10003
10004 /* Don't let the initial kboard remain current longer than necessary.
10005 That would cause problems if a file loaded on startup tries to
10006 prompt in the mini-buffer. */
10007 if (current_kboard == initial_kboard)
10008 current_kboard = terminal->kboard;
10009 }
10010 terminal->kboard->reference_count++;
10011 }
10012
10013 /* Put this display on the chain. */
10014 dpyinfo->next = x_display_list;
10015 x_display_list = dpyinfo;
10016
10017 /* Put it on x_display_name_list as well, to keep them parallel. */
10018 x_display_name_list = Fcons (Fcons (display_name, Qnil),
10019 x_display_name_list);
10020 dpyinfo->name_list_element = XCAR (x_display_name_list);
10021
10022 dpyinfo->display = dpy;
10023
10024 /* Set the name of the terminal. */
10025 terminal->name = xlispstrdup (display_name);
10026
10027 #if 0
10028 XSetAfterFunction (x_current_display, x_trace_wire);
10029 #endif /* ! 0 */
10030
10031 lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
10032 if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name))
10033 memory_full (SIZE_MAX);
10034 dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
10035 + SBYTES (Vsystem_name) + 2);
10036 strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"),
10037 SSDATA (Vsystem_name));
10038
10039 /* Figure out which modifier bits mean what. */
10040 x_find_modifier_meanings (dpyinfo);
10041
10042 /* Get the scroll bar cursor. */
10043 #ifdef USE_GTK
10044 /* We must create a GTK cursor, it is required for GTK widgets. */
10045 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
10046 #endif /* USE_GTK */
10047
10048 dpyinfo->vertical_scroll_bar_cursor
10049 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10050
10051 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10052 resource_name, EMACS_CLASS);
10053 #ifdef HAVE_XRMSETDATABASE
10054 XrmSetDatabase (dpyinfo->display, xrdb);
10055 #else
10056 dpyinfo->display->db = xrdb;
10057 #endif
10058 /* Put the rdb where we can find it in a way that works on
10059 all versions. */
10060 dpyinfo->xrdb = xrdb;
10061
10062 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
10063 DefaultScreen (dpyinfo->display));
10064 select_visual (dpyinfo);
10065 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
10066 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
10067 dpyinfo->icon_bitmap_id = -1;
10068 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
10069
10070 reset_mouse_highlight (&dpyinfo->mouse_highlight);
10071
10072 /* See if we can construct pixel values from RGB values. */
10073 if (dpyinfo->visual->class == TrueColor)
10074 {
10075 get_bits_and_offset (dpyinfo->visual->red_mask,
10076 &dpyinfo->red_bits, &dpyinfo->red_offset);
10077 get_bits_and_offset (dpyinfo->visual->blue_mask,
10078 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
10079 get_bits_and_offset (dpyinfo->visual->green_mask,
10080 &dpyinfo->green_bits, &dpyinfo->green_offset);
10081 }
10082
10083 /* See if a private colormap is requested. */
10084 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
10085 {
10086 if (dpyinfo->visual->class == PseudoColor)
10087 {
10088 Lisp_Object value;
10089 value = display_x_get_resource (dpyinfo,
10090 build_string ("privateColormap"),
10091 build_string ("PrivateColormap"),
10092 Qnil, Qnil);
10093 if (STRINGP (value)
10094 && (!strcmp (SSDATA (value), "true")
10095 || !strcmp (SSDATA (value), "on")))
10096 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10097 }
10098 }
10099 else
10100 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10101 dpyinfo->visual, AllocNone);
10102
10103 #ifdef HAVE_XFT
10104 {
10105 /* If we are using Xft, check dpi value in X resources.
10106 It is better we use it as well, since Xft will use it, as will all
10107 Gnome applications. If our real DPI is smaller or larger than the
10108 one Xft uses, our font will look smaller or larger than other
10109 for other applications, even if it is the same font name (monospace-10
10110 for example). */
10111 char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
10112 double d;
10113 if (v != NULL && sscanf (v, "%lf", &d) == 1)
10114 dpyinfo->resy = dpyinfo->resx = d;
10115 }
10116 #endif
10117
10118 if (dpyinfo->resy < 1)
10119 {
10120 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10121 double pixels = DisplayHeight (dpyinfo->display, screen_number);
10122 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
10123 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10124 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
10125 pixels = DisplayWidth (dpyinfo->display, screen_number);
10126 mm = DisplayWidthMM (dpyinfo->display, screen_number);
10127 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10128 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
10129 }
10130
10131 {
10132 static const struct
10133 {
10134 const char *name;
10135 int offset;
10136 } atom_refs[] = {
10137 #define ATOM_REFS_INIT(string, member) \
10138 { string, offsetof (struct x_display_info, member) },
10139 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
10140 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
10141 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
10142 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
10143 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
10144 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
10145 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
10146 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
10147 ATOM_REFS_INIT ("Editres", Xatom_editres)
10148 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
10149 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
10150 ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
10151 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
10152 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
10153 ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
10154 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
10155 ATOM_REFS_INIT ("INCR", Xatom_INCR)
10156 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
10157 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
10158 ATOM_REFS_INIT ("NULL", Xatom_NULL)
10159 ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
10160 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
10161 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
10162 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
10163 /* For properties of font. */
10164 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
10165 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
10166 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
10167 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
10168 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
10169 /* Ghostscript support. */
10170 ATOM_REFS_INIT ("DONE", Xatom_DONE)
10171 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
10172 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
10173 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
10174 /* EWMH */
10175 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
10176 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
10177 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
10178 Xatom_net_wm_state_maximized_horz)
10179 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
10180 Xatom_net_wm_state_maximized_vert)
10181 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
10182 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
10183 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
10184 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
10185 Xatom_net_window_type_tooltip)
10186 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
10187 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
10188 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
10189 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
10190 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
10191 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
10192 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
10193 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
10194 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
10195 /* Session management */
10196 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
10197 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
10198 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
10199 };
10200
10201 int i;
10202 const int atom_count = sizeof (atom_refs) / sizeof (atom_refs[0]);
10203 /* 1 for _XSETTINGS_SN */
10204 const int total_atom_count = 1 + atom_count;
10205 Atom *atoms_return = xmalloc (total_atom_count * sizeof *atoms_return);
10206 char **atom_names = xmalloc (total_atom_count * sizeof *atom_names);
10207 static char const xsettings_fmt[] = "_XSETTINGS_S%d";
10208 char xsettings_atom_name[sizeof xsettings_fmt - 2
10209 + INT_STRLEN_BOUND (int)];
10210
10211 for (i = 0; i < atom_count; i++)
10212 atom_names[i] = (char *) atom_refs[i].name;
10213
10214 /* Build _XSETTINGS_SN atom name */
10215 sprintf (xsettings_atom_name, xsettings_fmt,
10216 XScreenNumberOfScreen (dpyinfo->screen));
10217 atom_names[i] = xsettings_atom_name;
10218
10219 XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
10220 False, atoms_return);
10221
10222 for (i = 0; i < atom_count; i++)
10223 *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
10224
10225 /* Manual copy of last atom */
10226 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
10227
10228 xfree (atom_names);
10229 xfree (atoms_return);
10230 }
10231
10232 dpyinfo->x_dnd_atoms_size = 8;
10233 dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
10234 * dpyinfo->x_dnd_atoms_size);
10235
10236 connection = ConnectionNumber (dpyinfo->display);
10237 dpyinfo->connection = connection;
10238 dpyinfo->gray
10239 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10240 gray_bits, gray_width, gray_height,
10241 1, 0, 1);
10242
10243 #ifdef HAVE_X_I18N
10244 xim_initialize (dpyinfo, resource_name);
10245 #endif
10246
10247 xsettings_initialize (dpyinfo);
10248
10249 /* This is only needed for distinguishing keyboard and process input. */
10250 if (connection != 0)
10251 add_keyboard_wait_descriptor (connection);
10252
10253 #ifdef F_SETOWN
10254 fcntl (connection, F_SETOWN, getpid ());
10255 #endif /* ! defined (F_SETOWN) */
10256
10257 if (interrupt_input)
10258 init_sigio (connection);
10259
10260 #ifdef USE_LUCID
10261 {
10262 XrmValue d, fr, to;
10263 Font font;
10264
10265 dpy = dpyinfo->display;
10266 d.addr = (XPointer)&dpy;
10267 d.size = sizeof (Display *);
10268 fr.addr = XtDefaultFont;
10269 fr.size = sizeof (XtDefaultFont);
10270 to.size = sizeof (Font *);
10271 to.addr = (XPointer)&font;
10272 x_catch_errors (dpy);
10273 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
10274 emacs_abort ();
10275 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
10276 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
10277 x_uncatch_errors ();
10278 }
10279 #endif
10280
10281 /* See if we should run in synchronous mode. This is useful
10282 for debugging X code. */
10283 {
10284 Lisp_Object value;
10285 value = display_x_get_resource (dpyinfo,
10286 build_string ("synchronous"),
10287 build_string ("Synchronous"),
10288 Qnil, Qnil);
10289 if (STRINGP (value)
10290 && (!strcmp (SSDATA (value), "true")
10291 || !strcmp (SSDATA (value), "on")))
10292 XSynchronize (dpyinfo->display, True);
10293 }
10294
10295 {
10296 Lisp_Object value;
10297 value = display_x_get_resource (dpyinfo,
10298 build_string ("useXIM"),
10299 build_string ("UseXIM"),
10300 Qnil, Qnil);
10301 #ifdef USE_XIM
10302 if (STRINGP (value)
10303 && (!strcmp (SSDATA (value), "false")
10304 || !strcmp (SSDATA (value), "off")))
10305 use_xim = 0;
10306 #else
10307 if (STRINGP (value)
10308 && (!strcmp (SSDATA (value), "true")
10309 || !strcmp (SSDATA (value), "on")))
10310 use_xim = 1;
10311 #endif
10312 }
10313
10314 #ifdef HAVE_X_SM
10315 /* Only do this for the very first display in the Emacs session.
10316 Ignore X session management when Emacs was first started on a
10317 tty. */
10318 if (terminal->id == 1)
10319 x_session_initialize (dpyinfo);
10320 #endif
10321
10322 unblock_input ();
10323
10324 return dpyinfo;
10325 }
10326 \f
10327 /* Get rid of display DPYINFO, deleting all frames on it,
10328 and without sending any more commands to the X server. */
10329
10330 static void
10331 x_delete_display (struct x_display_info *dpyinfo)
10332 {
10333 struct terminal *t;
10334
10335 /* Close all frames and delete the generic struct terminal for this
10336 X display. */
10337 for (t = terminal_list; t; t = t->next_terminal)
10338 if (t->type == output_x_window && t->display_info.x == dpyinfo)
10339 {
10340 #ifdef HAVE_X_SM
10341 /* Close X session management when we close its display. */
10342 if (t->id == 1 && x_session_have_connection ())
10343 x_session_close ();
10344 #endif
10345 delete_terminal (t);
10346 break;
10347 }
10348
10349 delete_keyboard_wait_descriptor (dpyinfo->connection);
10350
10351 /* Discard this display from x_display_name_list and x_display_list.
10352 We can't use Fdelq because that can quit. */
10353 if (! NILP (x_display_name_list)
10354 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10355 x_display_name_list = XCDR (x_display_name_list);
10356 else
10357 {
10358 Lisp_Object tail;
10359
10360 tail = x_display_name_list;
10361 while (CONSP (tail) && CONSP (XCDR (tail)))
10362 {
10363 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10364 {
10365 XSETCDR (tail, XCDR (XCDR (tail)));
10366 break;
10367 }
10368 tail = XCDR (tail);
10369 }
10370 }
10371
10372 if (next_noop_dpyinfo == dpyinfo)
10373 next_noop_dpyinfo = dpyinfo->next;
10374
10375 if (x_display_list == dpyinfo)
10376 x_display_list = dpyinfo->next;
10377 else
10378 {
10379 struct x_display_info *tail;
10380
10381 for (tail = x_display_list; tail; tail = tail->next)
10382 if (tail->next == dpyinfo)
10383 tail->next = tail->next->next;
10384 }
10385
10386 xfree (dpyinfo->x_id_name);
10387 xfree (dpyinfo->x_dnd_atoms);
10388 xfree (dpyinfo->color_cells);
10389 xfree (dpyinfo);
10390 }
10391
10392 #ifdef USE_X_TOOLKIT
10393
10394 /* Atimer callback function for TIMER. Called every 0.1s to process
10395 Xt timeouts, if needed. We must avoid calling XtAppPending as
10396 much as possible because that function does an implicit XFlush
10397 that slows us down. */
10398
10399 static void
10400 x_process_timeouts (struct atimer *timer)
10401 {
10402 block_input ();
10403 x_timeout_atimer_activated_flag = 0;
10404 if (toolkit_scroll_bar_interaction || popup_activated ())
10405 {
10406 while (XtAppPending (Xt_app_con) & XtIMTimer)
10407 XtAppProcessEvent (Xt_app_con, XtIMTimer);
10408 /* Reactivate the atimer for next time. */
10409 x_activate_timeout_atimer ();
10410 }
10411 unblock_input ();
10412 }
10413
10414 /* Install an asynchronous timer that processes Xt timeout events
10415 every 0.1s as long as either `toolkit_scroll_bar_interaction' or
10416 `popup_activated_flag' (in xmenu.c) is set. Make sure to call this
10417 function whenever these variables are set. This is necessary
10418 because some widget sets use timeouts internally, for example the
10419 LessTif menu bar, or the Xaw3d scroll bar. When Xt timeouts aren't
10420 processed, these widgets don't behave normally. */
10421
10422 void
10423 x_activate_timeout_atimer (void)
10424 {
10425 block_input ();
10426 if (!x_timeout_atimer_activated_flag)
10427 {
10428 EMACS_TIME interval = make_emacs_time (0, 100 * 1000 * 1000);
10429 start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
10430 x_timeout_atimer_activated_flag = 1;
10431 }
10432 unblock_input ();
10433 }
10434
10435 #endif /* USE_X_TOOLKIT */
10436
10437 \f
10438 /* Set up use of X before we make the first connection. */
10439
10440 static struct redisplay_interface x_redisplay_interface =
10441 {
10442 x_frame_parm_handlers,
10443 x_produce_glyphs,
10444 x_write_glyphs,
10445 x_insert_glyphs,
10446 x_clear_end_of_line,
10447 x_scroll_run,
10448 x_after_update_window_line,
10449 x_update_window_begin,
10450 x_update_window_end,
10451 x_cursor_to,
10452 x_flush,
10453 #ifdef XFlush
10454 x_flush,
10455 #else
10456 0, /* flush_display_optional */
10457 #endif
10458 x_clear_window_mouse_face,
10459 x_get_glyph_overhangs,
10460 x_fix_overlapping_area,
10461 x_draw_fringe_bitmap,
10462 0, /* define_fringe_bitmap */
10463 0, /* destroy_fringe_bitmap */
10464 x_compute_glyph_string_overhangs,
10465 x_draw_glyph_string,
10466 x_define_frame_cursor,
10467 x_clear_frame_area,
10468 x_draw_window_cursor,
10469 x_draw_vertical_window_border,
10470 x_shift_glyphs_for_insert
10471 };
10472
10473
10474 /* This function is called when the last frame on a display is deleted. */
10475 void
10476 x_delete_terminal (struct terminal *terminal)
10477 {
10478 struct x_display_info *dpyinfo = terminal->display_info.x;
10479
10480 /* Protect against recursive calls. delete_frame in
10481 delete_terminal calls us back when it deletes our last frame. */
10482 if (!terminal->name)
10483 return;
10484
10485 block_input ();
10486 #ifdef HAVE_X_I18N
10487 /* We must close our connection to the XIM server before closing the
10488 X display. */
10489 if (dpyinfo->xim)
10490 xim_close_dpy (dpyinfo);
10491 #endif
10492
10493 /* If called from x_connection_closed, the display may already be closed
10494 and dpyinfo->display was set to 0 to indicate that. */
10495 if (dpyinfo->display)
10496 {
10497 x_destroy_all_bitmaps (dpyinfo);
10498 XSetCloseDownMode (dpyinfo->display, DestroyAll);
10499
10500 /* Whether or not XCloseDisplay destroys the associated resource
10501 database depends on the version of libX11. To avoid both
10502 crash and memory leak, we dissociate the database from the
10503 display and then destroy dpyinfo->xrdb ourselves.
10504
10505 Unfortunately, the above strategy does not work in some
10506 situations due to a bug in newer versions of libX11: because
10507 XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
10508 dpy->db is NULL, XCloseDisplay destroys the associated
10509 database whereas it has not been created by XGetDefault
10510 (Bug#21974 in freedesktop.org Bugzilla). As a workaround, we
10511 don't destroy the database here in order to avoid the crash
10512 in the above situations for now, though that may cause memory
10513 leaks in other situations. */
10514 #if 0
10515 #ifdef HAVE_XRMSETDATABASE
10516 XrmSetDatabase (dpyinfo->display, NULL);
10517 #else
10518 dpyinfo->display->db = NULL;
10519 #endif
10520 /* We used to call XrmDestroyDatabase from x_delete_display, but
10521 some older versions of libX11 crash if we call it after
10522 closing all the displays. */
10523 XrmDestroyDatabase (dpyinfo->xrdb);
10524 #endif
10525
10526 #ifdef USE_GTK
10527 xg_display_close (dpyinfo->display);
10528 #else
10529 #ifdef USE_X_TOOLKIT
10530 XtCloseDisplay (dpyinfo->display);
10531 #else
10532 XCloseDisplay (dpyinfo->display);
10533 #endif
10534 #endif /* ! USE_GTK */
10535 }
10536
10537 /* Mark as dead. */
10538 dpyinfo->display = NULL;
10539 x_delete_display (dpyinfo);
10540 unblock_input ();
10541 }
10542
10543 /* Create a struct terminal, initialize it with the X11 specific
10544 functions and make DISPLAY->TERMINAL point to it. */
10545
10546 static struct terminal *
10547 x_create_terminal (struct x_display_info *dpyinfo)
10548 {
10549 struct terminal *terminal;
10550
10551 terminal = create_terminal ();
10552
10553 terminal->type = output_x_window;
10554 terminal->display_info.x = dpyinfo;
10555 dpyinfo->terminal = terminal;
10556
10557 /* kboard is initialized in x_term_init. */
10558
10559 terminal->clear_frame_hook = x_clear_frame;
10560 terminal->ins_del_lines_hook = x_ins_del_lines;
10561 terminal->delete_glyphs_hook = x_delete_glyphs;
10562 terminal->ring_bell_hook = XTring_bell;
10563 terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
10564 terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
10565 terminal->set_terminal_modes_hook = XTset_terminal_modes;
10566 terminal->update_begin_hook = x_update_begin;
10567 terminal->update_end_hook = x_update_end;
10568 terminal->set_terminal_window_hook = XTset_terminal_window;
10569 terminal->read_socket_hook = XTread_socket;
10570 terminal->frame_up_to_date_hook = XTframe_up_to_date;
10571 terminal->mouse_position_hook = XTmouse_position;
10572 terminal->frame_rehighlight_hook = XTframe_rehighlight;
10573 terminal->frame_raise_lower_hook = XTframe_raise_lower;
10574 terminal->fullscreen_hook = XTfullscreen_hook;
10575 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10576 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10577 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10578 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
10579
10580 terminal->delete_frame_hook = x_destroy_window;
10581 terminal->delete_terminal_hook = x_delete_terminal;
10582
10583 terminal->rif = &x_redisplay_interface;
10584 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
10585 terminal->char_ins_del_ok = 1;
10586 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
10587 terminal->fast_clear_end_of_line = 1; /* X does this well. */
10588 terminal->memory_below_frame = 0; /* We don't remember what scrolls
10589 off the bottom. */
10590
10591 return terminal;
10592 }
10593
10594 void
10595 x_initialize (void)
10596 {
10597 baud_rate = 19200;
10598
10599 x_noop_count = 0;
10600 last_tool_bar_item = -1;
10601 any_help_event_p = 0;
10602 ignore_next_mouse_click_timeout = 0;
10603
10604 #ifdef USE_GTK
10605 current_count = -1;
10606 #endif
10607
10608 /* Try to use interrupt input; if we can't, then start polling. */
10609 Fset_input_interrupt_mode (Qt);
10610
10611 #ifdef USE_X_TOOLKIT
10612 XtToolkitInitialize ();
10613
10614 Xt_app_con = XtCreateApplicationContext ();
10615
10616 /* Register a converter from strings to pixels, which uses
10617 Emacs' color allocation infrastructure. */
10618 XtAppSetTypeConverter (Xt_app_con,
10619 XtRString, XtRPixel, cvt_string_to_pixel,
10620 cvt_string_to_pixel_args,
10621 XtNumber (cvt_string_to_pixel_args),
10622 XtCacheByDisplay, cvt_pixel_dtor);
10623
10624 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
10625 #endif
10626
10627 #ifdef USE_TOOLKIT_SCROLL_BARS
10628 #ifndef USE_GTK
10629 xaw3d_arrow_scroll = False;
10630 xaw3d_pick_top = True;
10631 #endif
10632 #endif
10633
10634 pending_autoraise_frame = 0;
10635 pending_event_wait.f = 0;
10636 pending_event_wait.eventtype = 0;
10637
10638 /* Note that there is no real way portable across R3/R4 to get the
10639 original error handler. */
10640 XSetErrorHandler (x_error_handler);
10641 XSetIOErrorHandler (x_io_error_quitter);
10642 }
10643
10644
10645 void
10646 syms_of_xterm (void)
10647 {
10648 x_error_message = NULL;
10649
10650 staticpro (&x_display_name_list);
10651 x_display_name_list = Qnil;
10652
10653 staticpro (&last_mouse_scroll_bar);
10654 last_mouse_scroll_bar = Qnil;
10655
10656 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
10657 DEFSYM (Qlatin_1, "latin-1");
10658
10659 #ifdef USE_GTK
10660 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
10661 staticpro (&xg_default_icon_file);
10662
10663 DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
10664 #endif
10665
10666 DEFVAR_BOOL ("x-use-underline-position-properties",
10667 x_use_underline_position_properties,
10668 doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
10669 A value of nil means ignore them. If you encounter fonts with bogus
10670 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10671 to 4.1, set this to nil. You can also use `underline-minimum-offset'
10672 to override the font's UNDERLINE_POSITION for small font display
10673 sizes. */);
10674 x_use_underline_position_properties = 1;
10675
10676 DEFVAR_BOOL ("x-underline-at-descent-line",
10677 x_underline_at_descent_line,
10678 doc: /* Non-nil means to draw the underline at the same place as the descent line.
10679 A value of nil means to draw the underline according to the value of the
10680 variable `x-use-underline-position-properties', which is usually at the
10681 baseline level. The default value is nil. */);
10682 x_underline_at_descent_line = 0;
10683
10684 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10685 x_mouse_click_focus_ignore_position,
10686 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
10687 This variable is only used when the window manager requires that you
10688 click on a frame to select it (give it focus). In that case, a value
10689 of nil, means that the selected window and cursor position changes to
10690 reflect the mouse click position, while a non-nil value means that the
10691 selected window or cursor position is preserved. */);
10692 x_mouse_click_focus_ignore_position = 0;
10693
10694 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
10695 doc: /* Which toolkit scroll bars Emacs uses, if any.
10696 A value of nil means Emacs doesn't use toolkit scroll bars.
10697 With the X Window system, the value is a symbol describing the
10698 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
10699 With MS Windows or Nextstep, the value is t. */);
10700 #ifdef USE_TOOLKIT_SCROLL_BARS
10701 #ifdef USE_MOTIF
10702 Vx_toolkit_scroll_bars = intern_c_string ("motif");
10703 #elif defined HAVE_XAW3D
10704 Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
10705 #elif USE_GTK
10706 Vx_toolkit_scroll_bars = intern_c_string ("gtk");
10707 #else
10708 Vx_toolkit_scroll_bars = intern_c_string ("xaw");
10709 #endif
10710 #else
10711 Vx_toolkit_scroll_bars = Qnil;
10712 #endif
10713
10714 staticpro (&last_mouse_motion_frame);
10715 last_mouse_motion_frame = Qnil;
10716
10717 Qmodifier_value = intern_c_string ("modifier-value");
10718 Qalt = intern_c_string ("alt");
10719 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10720 Qhyper = intern_c_string ("hyper");
10721 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10722 Qmeta = intern_c_string ("meta");
10723 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10724 Qsuper = intern_c_string ("super");
10725 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10726
10727 DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
10728 doc: /* Which keys Emacs uses for the alt modifier.
10729 This should be one of the symbols `alt', `hyper', `meta', `super'.
10730 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10731 is nil, which is the same as `alt'. */);
10732 Vx_alt_keysym = Qnil;
10733
10734 DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
10735 doc: /* Which keys Emacs uses for the hyper modifier.
10736 This should be one of the symbols `alt', `hyper', `meta', `super'.
10737 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10738 default is nil, which is the same as `hyper'. */);
10739 Vx_hyper_keysym = Qnil;
10740
10741 DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
10742 doc: /* Which keys Emacs uses for the meta modifier.
10743 This should be one of the symbols `alt', `hyper', `meta', `super'.
10744 For example, `meta' means use the Meta_L and Meta_R keysyms. The
10745 default is nil, which is the same as `meta'. */);
10746 Vx_meta_keysym = Qnil;
10747
10748 DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
10749 doc: /* Which keys Emacs uses for the super modifier.
10750 This should be one of the symbols `alt', `hyper', `meta', `super'.
10751 For example, `super' means use the Super_L and Super_R keysyms. The
10752 default is nil, which is the same as `super'. */);
10753 Vx_super_keysym = Qnil;
10754
10755 DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
10756 doc: /* Hash table of character codes indexed by X keysym codes. */);
10757 Vx_keysym_table = make_hash_table (hashtest_eql, make_number (900),
10758 make_float (DEFAULT_REHASH_SIZE),
10759 make_float (DEFAULT_REHASH_THRESHOLD),
10760 Qnil);
10761 }
10762
10763 #endif /* HAVE_X_WINDOWS */