Fix setting icon for Gtk+ on non-initial frame.
[emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2
3 Copyright (C) 1989, 1993-2014 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 #include "lisp.h"
27 #include "blockinput.h"
28 #include "syssignal.h"
29
30 /* This may include sys/types.h, and that somehow loses
31 if this is not done before the other system files. */
32 #include "xterm.h"
33 #include <X11/cursorfont.h>
34
35 /* If we have Xfixes extension, use it for pointer blanking. */
36 #ifdef HAVE_XFIXES
37 #include <X11/extensions/Xfixes.h>
38 #endif
39
40 /* Using Xft implies that XRender is available. */
41 #ifdef HAVE_XFT
42 #include <X11/extensions/Xrender.h>
43 #endif
44
45 /* Load sys/types.h if not already loaded.
46 In some systems loading it twice is suicidal. */
47 #ifndef makedev
48 #include <sys/types.h>
49 #endif /* makedev */
50
51 #include <sys/ioctl.h>
52
53 #include "systime.h"
54
55 #include <fcntl.h>
56 #include <errno.h>
57 #include <sys/stat.h>
58 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
59 /* #include <sys/param.h> */
60
61 #include "charset.h"
62 #include "character.h"
63 #include "coding.h"
64 #include "frame.h"
65 #include "dispextern.h"
66 #include "fontset.h"
67 #include "termhooks.h"
68 #include "termopts.h"
69 #include "termchar.h"
70 #include "emacs-icon.h"
71 #include "disptab.h"
72 #include "buffer.h"
73 #include "window.h"
74 #include "keyboard.h"
75 #include "intervals.h"
76 #include "process.h"
77 #include "atimer.h"
78 #include "keymap.h"
79 #include "font.h"
80 #include "xsettings.h"
81 #include "xgselect.h"
82 #include "sysselect.h"
83 #include "menu.h"
84
85 #ifdef USE_X_TOOLKIT
86 #include <X11/Shell.h>
87 #endif
88
89 #include <unistd.h>
90
91 #ifdef USE_GTK
92 #include "gtkutil.h"
93 #ifdef HAVE_GTK3
94 #include <X11/Xproto.h>
95 #endif
96 #endif
97
98 #if defined (USE_LUCID) || defined (USE_MOTIF)
99 #include "../lwlib/xlwmenu.h"
100 #endif
101
102 #ifdef USE_X_TOOLKIT
103 #if !defined (NO_EDITRES)
104 #define HACK_EDITRES
105 extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
106 #endif /* not NO_EDITRES */
107
108 /* Include toolkit specific headers for the scroll bar widget. */
109
110 #ifdef USE_TOOLKIT_SCROLL_BARS
111 #if defined USE_MOTIF
112 #include <Xm/Xm.h> /* For LESSTIF_VERSION */
113 #include <Xm/ScrollBar.h>
114 #else /* !USE_MOTIF i.e. use Xaw */
115
116 #ifdef HAVE_XAW3D
117 #include <X11/Xaw3d/Simple.h>
118 #include <X11/Xaw3d/Scrollbar.h>
119 #include <X11/Xaw3d/ThreeD.h>
120 #else /* !HAVE_XAW3D */
121 #include <X11/Xaw/Simple.h>
122 #include <X11/Xaw/Scrollbar.h>
123 #endif /* !HAVE_XAW3D */
124 #ifndef XtNpickTop
125 #define XtNpickTop "pickTop"
126 #endif /* !XtNpickTop */
127 #endif /* !USE_MOTIF */
128 #endif /* USE_TOOLKIT_SCROLL_BARS */
129
130 #endif /* USE_X_TOOLKIT */
131
132 #ifdef USE_X_TOOLKIT
133 #include "widget.h"
134 #ifndef XtNinitialState
135 #define XtNinitialState "initialState"
136 #endif
137 #endif
138
139 #include "bitmaps/gray.xbm"
140
141 #ifdef HAVE_XKB
142 #include <X11/XKBlib.h>
143 #endif
144
145 /* Default to using XIM if available. */
146 #ifdef USE_XIM
147 bool use_xim = true;
148 #else
149 bool use_xim = false; /* configure --without-xim */
150 #endif
151
152 /* Non-zero means that a HELP_EVENT has been generated since Emacs
153 start. */
154
155 static bool any_help_event_p;
156
157 /* This is a chain of structures for all the X displays currently in
158 use. */
159
160 struct x_display_info *x_display_list;
161
162 #ifdef USE_X_TOOLKIT
163
164 /* The application context for Xt use. */
165 XtAppContext Xt_app_con;
166 static String Xt_default_resources[] = {0};
167
168 /* Non-zero means user is interacting with a toolkit scroll bar. */
169 static bool toolkit_scroll_bar_interaction;
170
171 #endif /* USE_X_TOOLKIT */
172
173 /* Non-zero timeout value means ignore next mouse click if it arrives
174 before that timeout elapses (i.e. as part of the same sequence of
175 events resulting from clicking on a frame to select it). */
176
177 static Time ignore_next_mouse_click_timeout;
178
179 /* Used locally within XTread_socket. */
180
181 static int x_noop_count;
182
183 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
184
185 static Lisp_Object Qvendor_specific_keysyms;
186 static Lisp_Object Qlatin_1;
187
188 #ifdef USE_GTK
189 /* The name of the Emacs icon file. */
190 static Lisp_Object xg_default_icon_file;
191
192 /* Used in gtkutil.c. */
193 Lisp_Object Qx_gtk_map_stock;
194 #endif
195
196 /* Some functions take this as char *, not const char *. */
197 static char emacs_class[] = EMACS_CLASS;
198
199 enum xembed_info
200 {
201 XEMBED_MAPPED = 1 << 0
202 };
203
204 enum xembed_message
205 {
206 XEMBED_EMBEDDED_NOTIFY = 0,
207 XEMBED_WINDOW_ACTIVATE = 1,
208 XEMBED_WINDOW_DEACTIVATE = 2,
209 XEMBED_REQUEST_FOCUS = 3,
210 XEMBED_FOCUS_IN = 4,
211 XEMBED_FOCUS_OUT = 5,
212 XEMBED_FOCUS_NEXT = 6,
213 XEMBED_FOCUS_PREV = 7,
214
215 XEMBED_MODALITY_ON = 10,
216 XEMBED_MODALITY_OFF = 11,
217 XEMBED_REGISTER_ACCELERATOR = 12,
218 XEMBED_UNREGISTER_ACCELERATOR = 13,
219 XEMBED_ACTIVATE_ACCELERATOR = 14
220 };
221
222 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
223 static void x_set_window_size_1 (struct frame *, bool, int, int, bool);
224 static void x_raise_frame (struct frame *);
225 static void x_lower_frame (struct frame *);
226 static const XColor *x_color_cells (Display *, int *);
227 static int x_io_error_quitter (Display *);
228 static struct terminal *x_create_terminal (struct x_display_info *);
229 static void x_update_end (struct frame *);
230 static void XTframe_up_to_date (struct frame *);
231 static void x_clear_frame (struct frame *);
232 static _Noreturn void x_ins_del_lines (struct frame *, int, int);
233 static void frame_highlight (struct frame *);
234 static void frame_unhighlight (struct frame *);
235 static void x_new_focus_frame (struct x_display_info *, struct frame *);
236 static void x_focus_changed (int, int, struct x_display_info *,
237 struct frame *, struct input_event *);
238 static void XTframe_rehighlight (struct frame *);
239 static void x_frame_rehighlight (struct x_display_info *);
240 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
241 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
242 enum text_cursor_kinds);
243
244 static void x_clip_to_row (struct window *, struct glyph_row *,
245 enum glyph_row_area, GC);
246 static void x_flush (struct frame *f);
247 static void x_update_begin (struct frame *);
248 static void x_update_window_begin (struct window *);
249 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
250 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
251 enum scroll_bar_part *,
252 Lisp_Object *, Lisp_Object *,
253 Time *);
254 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
255 enum scroll_bar_part *,
256 Lisp_Object *, Lisp_Object *,
257 Time *);
258 static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
259 static void x_check_fullscreen (struct frame *);
260 static void x_check_expected_move (struct frame *, int, int);
261 static void x_sync_with_move (struct frame *, int, int, bool);
262 static int handle_one_xevent (struct x_display_info *,
263 const XEvent *, int *,
264 struct input_event *);
265 #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
266 static int x_dispatch_event (XEvent *, Display *);
267 #endif
268 /* Don't declare this _Noreturn because we want no
269 interference with debugging failing X calls. */
270 static void x_connection_closed (Display *, const char *);
271 static void x_wm_set_window_state (struct frame *, int);
272 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
273 static void x_initialize (void);
274
275 static bool get_current_wm_state (struct frame *, Window, int *, bool *);
276
277 /* Flush display of frame F. */
278
279 static void
280 x_flush (struct frame *f)
281 {
282 eassert (f && FRAME_X_P (f));
283 /* Don't call XFlush when it is not safe to redisplay; the X
284 connection may be broken. */
285 if (!NILP (Vinhibit_redisplay))
286 return;
287
288 block_input ();
289 XFlush (FRAME_X_DISPLAY (f));
290 unblock_input ();
291 }
292
293
294 /* Remove calls to XFlush by defining XFlush to an empty replacement.
295 Calls to XFlush should be unnecessary because the X output buffer
296 is flushed automatically as needed by calls to XPending,
297 XNextEvent, or XWindowEvent according to the XFlush man page.
298 XTread_socket calls XPending. Removing XFlush improves
299 performance. */
300
301 #define XFlush(DISPLAY) (void) 0
302
303 \f
304 /***********************************************************************
305 Debugging
306 ***********************************************************************/
307
308 #if false
309
310 /* This is a function useful for recording debugging information about
311 the sequence of occurrences in this file. */
312
313 struct record
314 {
315 char *locus;
316 int type;
317 };
318
319 struct record event_record[100];
320
321 int event_record_index;
322
323 void
324 record_event (char *locus, int type)
325 {
326 if (event_record_index == ARRAYELTS (event_record))
327 event_record_index = 0;
328
329 event_record[event_record_index].locus = locus;
330 event_record[event_record_index].type = type;
331 event_record_index++;
332 }
333
334 #endif
335
336
337 \f
338 /* Return the struct x_display_info corresponding to DPY. */
339
340 struct x_display_info *
341 x_display_info_for_display (Display *dpy)
342 {
343 struct x_display_info *dpyinfo;
344
345 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
346 if (dpyinfo->display == dpy)
347 return dpyinfo;
348
349 return 0;
350 }
351
352 static Window
353 x_find_topmost_parent (struct frame *f)
354 {
355 struct x_output *x = f->output_data.x;
356 Window win = None, wi = x->parent_desc;
357 Display *dpy = FRAME_X_DISPLAY (f);
358
359 while (wi != FRAME_DISPLAY_INFO (f)->root_window)
360 {
361 Window root;
362 Window *children;
363 unsigned int nchildren;
364
365 win = wi;
366 if (XQueryTree (dpy, win, &root, &wi, &children, &nchildren))
367 XFree (children);
368 else
369 break;
370 }
371
372 return win;
373 }
374
375 #define OPAQUE 0xffffffff
376
377 void
378 x_set_frame_alpha (struct frame *f)
379 {
380 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
381 Display *dpy = FRAME_X_DISPLAY (f);
382 Window win = FRAME_OUTER_WINDOW (f);
383 double alpha = 1.0;
384 double alpha_min = 1.0;
385 unsigned long opac;
386 Window parent;
387
388 if (dpyinfo->x_highlight_frame == f)
389 alpha = f->alpha[0];
390 else
391 alpha = f->alpha[1];
392
393 if (FLOATP (Vframe_alpha_lower_limit))
394 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
395 else if (INTEGERP (Vframe_alpha_lower_limit))
396 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
397
398 if (alpha < 0.0)
399 return;
400 else if (alpha > 1.0)
401 alpha = 1.0;
402 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
403 alpha = alpha_min;
404
405 opac = alpha * OPAQUE;
406
407 x_catch_errors (dpy);
408
409 /* If there is a parent from the window manager, put the property there
410 also, to work around broken window managers that fail to do that.
411 Do this unconditionally as this function is called on reparent when
412 alpha has not changed on the frame. */
413
414 parent = x_find_topmost_parent (f);
415 if (parent != None)
416 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
417 XA_CARDINAL, 32, PropModeReplace,
418 (unsigned char *) &opac, 1);
419
420 /* return unless necessary */
421 {
422 unsigned char *data;
423 Atom actual;
424 int rc, format;
425 unsigned long n, left;
426
427 rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
428 0, 1, False, XA_CARDINAL,
429 &actual, &format, &n, &left,
430 &data);
431
432 if (rc == Success && actual != None)
433 {
434 unsigned long value = *(unsigned long *)data;
435 XFree (data);
436 if (value == opac)
437 {
438 x_uncatch_errors ();
439 return;
440 }
441 }
442 }
443
444 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
445 XA_CARDINAL, 32, PropModeReplace,
446 (unsigned char *) &opac, 1);
447 x_uncatch_errors ();
448 }
449
450 /***********************************************************************
451 Starting and ending an update
452 ***********************************************************************/
453
454 /* Start an update of frame F. This function is installed as a hook
455 for update_begin, i.e. it is called when update_begin is called.
456 This function is called prior to calls to x_update_window_begin for
457 each window being updated. Currently, there is nothing to do here
458 because all interesting stuff is done on a window basis. */
459
460 static void
461 x_update_begin (struct frame *f)
462 {
463 /* Nothing to do. */
464 }
465
466
467 /* Start update of window W. */
468
469 static void
470 x_update_window_begin (struct window *w)
471 {
472 struct frame *f = XFRAME (WINDOW_FRAME (w));
473 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
474
475 w->output_cursor = w->cursor;
476
477 block_input ();
478
479 if (f == hlinfo->mouse_face_mouse_frame)
480 {
481 /* Don't do highlighting for mouse motion during the update. */
482 hlinfo->mouse_face_defer = true;
483
484 /* If F needs to be redrawn, simply forget about any prior mouse
485 highlighting. */
486 if (FRAME_GARBAGED_P (f))
487 hlinfo->mouse_face_window = Qnil;
488 }
489
490 unblock_input ();
491 }
492
493
494 /* Draw a vertical window border from (x,y0) to (x,y1) */
495
496 static void
497 x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
498 {
499 struct frame *f = XFRAME (WINDOW_FRAME (w));
500 struct face *face;
501
502 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
503 if (face)
504 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
505 face->foreground);
506
507 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
508 f->output_data.x->normal_gc, x, y0, x, y1);
509 }
510
511 /* Draw a window divider from (x0,y0) to (x1,y1) */
512
513 static void
514 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
515 {
516 struct frame *f = XFRAME (WINDOW_FRAME (w));
517 struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
518 struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
519 struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
520 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
521 unsigned long color_first = (face_first
522 ? face_first->foreground
523 : FRAME_FOREGROUND_PIXEL (f));
524 unsigned long color_last = (face_last
525 ? face_last->foreground
526 : FRAME_FOREGROUND_PIXEL (f));
527 Display *display = FRAME_X_DISPLAY (f);
528 Window window = FRAME_X_WINDOW (f);
529
530 if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
531 /* Vertical. */
532 {
533 XSetForeground (display, f->output_data.x->normal_gc, color_first);
534 XFillRectangle (display, window, f->output_data.x->normal_gc,
535 x0, y0, 1, y1 - y0);
536 XSetForeground (display, f->output_data.x->normal_gc, color);
537 XFillRectangle (display, window, f->output_data.x->normal_gc,
538 x0 + 1, y0, x1 - x0 - 2, y1 - y0);
539 XSetForeground (display, f->output_data.x->normal_gc, color_last);
540 XFillRectangle (display, window, f->output_data.x->normal_gc,
541 x1 - 1, y0, 1, y1 - y0);
542 }
543 else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
544 /* Horizontal. */
545 {
546 XSetForeground (display, f->output_data.x->normal_gc, color_first);
547 XFillRectangle (display, window, f->output_data.x->normal_gc,
548 x0, y0, x1 - x0, 1);
549 XSetForeground (display, f->output_data.x->normal_gc, color);
550 XFillRectangle (display, window, f->output_data.x->normal_gc,
551 x0, y0 + 1, x1 - x0, y1 - y0 - 2);
552 XSetForeground (display, f->output_data.x->normal_gc, color_last);
553 XFillRectangle (display, window, f->output_data.x->normal_gc,
554 x0, y1 - 1, x1 - x0, 1);
555 }
556 else
557 {
558 XSetForeground (display, f->output_data.x->normal_gc, color);
559 XFillRectangle (display, window, f->output_data.x->normal_gc,
560 x0, y0, x1 - x0, y1 - y0);
561 }
562 }
563
564 /* End update of window W.
565
566 Draw vertical borders between horizontally adjacent windows, and
567 display W's cursor if CURSOR_ON_P is non-zero.
568
569 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
570 glyphs in mouse-face were overwritten. In that case we have to
571 make sure that the mouse-highlight is properly redrawn.
572
573 W may be a menu bar pseudo-window in case we don't have X toolkit
574 support. Such windows don't have a cursor, so don't display it
575 here. */
576
577 static void
578 x_update_window_end (struct window *w, bool cursor_on_p,
579 bool mouse_face_overwritten_p)
580 {
581 if (!w->pseudo_window_p)
582 {
583 block_input ();
584
585 if (cursor_on_p)
586 display_and_set_cursor (w, true,
587 w->output_cursor.hpos, w->output_cursor.vpos,
588 w->output_cursor.x, w->output_cursor.y);
589
590 if (draw_window_fringes (w, true))
591 {
592 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
593 x_draw_right_divider (w);
594 else
595 x_draw_vertical_border (w);
596 }
597
598 unblock_input ();
599 }
600
601 /* If a row with mouse-face was overwritten, arrange for
602 XTframe_up_to_date to redisplay the mouse highlight. */
603 if (mouse_face_overwritten_p)
604 {
605 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
606
607 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
608 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
609 hlinfo->mouse_face_window = Qnil;
610 }
611 }
612
613
614 /* End update of frame F. This function is installed as a hook in
615 update_end. */
616
617 static void
618 x_update_end (struct frame *f)
619 {
620 /* Mouse highlight may be displayed again. */
621 MOUSE_HL_INFO (f)->mouse_face_defer = false;
622
623 #ifndef XFlush
624 block_input ();
625 XFlush (FRAME_X_DISPLAY (f));
626 unblock_input ();
627 #endif
628 }
629
630
631 /* This function is called from various places in xdisp.c
632 whenever a complete update has been performed. */
633
634 static void
635 XTframe_up_to_date (struct frame *f)
636 {
637 if (FRAME_X_P (f))
638 FRAME_MOUSE_UPDATE (f);
639 }
640
641
642 /* Clear under internal border if any (GTK has its own version). */
643 #ifndef USE_GTK
644 void
645 x_clear_under_internal_border (struct frame *f)
646 {
647 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
648 {
649 Display *display = FRAME_X_DISPLAY (f);
650 Window window = FRAME_X_WINDOW (f);
651 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
652 int width = FRAME_PIXEL_WIDTH (f);
653 int height = FRAME_PIXEL_HEIGHT (f);
654 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
655
656 block_input ();
657 x_clear_area (display, window, 0, 0, border, height);
658 x_clear_area (display, window, 0, margin, width, border);
659 x_clear_area (display, window, width - border, 0, border, height);
660 x_clear_area (display, window, 0, height - border, width, border);
661 unblock_input ();
662 }
663 }
664 #endif
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 eassert (w);
676
677 if (!desired_row->mode_line_p && !w->pseudo_window_p)
678 desired_row->redraw_fringe_bitmaps_p = true;
679
680 #ifdef USE_X_TOOLKIT
681 /* When a window has disappeared, make sure that no rest of
682 full-width rows stays visible in the internal border. Could
683 check here if updated window is the leftmost/rightmost window,
684 but I guess it's not worth doing since vertically split windows
685 are almost never used, internal border is rarely set, and the
686 overhead is very small. */
687 {
688 struct frame *f;
689 int width, height;
690
691 if (windows_or_buffers_changed
692 && desired_row->full_width_p
693 && (f = XFRAME (w->frame),
694 width = FRAME_INTERNAL_BORDER_WIDTH (f),
695 width != 0)
696 && (height = desired_row->visible_height,
697 height > 0))
698 {
699 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
700
701 block_input ();
702 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
703 0, y, width, height);
704 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
705 FRAME_PIXEL_WIDTH (f) - width,
706 y, width, height);
707 unblock_input ();
708 }
709 }
710 #endif
711 }
712
713 static void
714 x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
715 {
716 struct frame *f = XFRAME (WINDOW_FRAME (w));
717 Display *display = FRAME_X_DISPLAY (f);
718 Window window = FRAME_X_WINDOW (f);
719 GC gc = f->output_data.x->normal_gc;
720 struct face *face = p->face;
721
722 /* Must clip because of partially visible lines. */
723 x_clip_to_row (w, row, ANY_AREA, gc);
724
725 if (p->bx >= 0 && !p->overlay_p)
726 {
727 /* In case the same realized face is used for fringes and
728 for something displayed in the text (e.g. face `region' on
729 mono-displays, the fill style may have been changed to
730 FillSolid in x_draw_glyph_string_background. */
731 if (face->stipple)
732 XSetFillStyle (display, face->gc, FillOpaqueStippled);
733 else
734 XSetForeground (display, face->gc, face->background);
735
736 XFillRectangle (display, window, face->gc,
737 p->bx, p->by, p->nx, p->ny);
738
739 if (!face->stipple)
740 XSetForeground (display, face->gc, face->foreground);
741 }
742
743 if (p->which)
744 {
745 char *bits;
746 Pixmap pixmap, clipmask = (Pixmap) 0;
747 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
748 XGCValues gcv;
749
750 if (p->wd > 8)
751 bits = (char *) (p->bits + p->dh);
752 else
753 bits = (char *) p->bits + p->dh;
754
755 /* Draw the bitmap. I believe these small pixmaps can be cached
756 by the server. */
757 pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
758 (p->cursor_p
759 ? (p->overlay_p ? face->background
760 : f->output_data.x->cursor_pixel)
761 : face->foreground),
762 face->background, depth);
763
764 if (p->overlay_p)
765 {
766 clipmask = XCreatePixmapFromBitmapData (display,
767 FRAME_DISPLAY_INFO (f)->root_window,
768 bits, p->wd, p->h,
769 1, 0, 1);
770 gcv.clip_mask = clipmask;
771 gcv.clip_x_origin = p->x;
772 gcv.clip_y_origin = p->y;
773 XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
774 }
775
776 XCopyArea (display, pixmap, window, gc, 0, 0,
777 p->wd, p->h, p->x, p->y);
778 XFreePixmap (display, pixmap);
779
780 if (p->overlay_p)
781 {
782 gcv.clip_mask = (Pixmap) 0;
783 XChangeGC (display, gc, GCClipMask, &gcv);
784 XFreePixmap (display, clipmask);
785 }
786 }
787
788 XSetClipMask (display, gc, None);
789 }
790
791 /***********************************************************************
792 Glyph display
793 ***********************************************************************/
794
795
796
797 static void x_set_glyph_string_clipping (struct glyph_string *);
798 static void x_set_glyph_string_gc (struct glyph_string *);
799 static void x_draw_glyph_string_foreground (struct glyph_string *);
800 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
801 static void x_draw_glyph_string_box (struct glyph_string *);
802 static void x_draw_glyph_string (struct glyph_string *);
803 static _Noreturn void x_delete_glyphs (struct frame *, int);
804 static void x_compute_glyph_string_overhangs (struct glyph_string *);
805 static void x_set_cursor_gc (struct glyph_string *);
806 static void x_set_mode_line_face_gc (struct glyph_string *);
807 static void x_set_mouse_face_gc (struct glyph_string *);
808 static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
809 unsigned long *, double, int);
810 static void x_setup_relief_color (struct frame *, struct relief *,
811 double, int, unsigned long);
812 static void x_setup_relief_colors (struct glyph_string *);
813 static void x_draw_image_glyph_string (struct glyph_string *);
814 static void x_draw_image_relief (struct glyph_string *);
815 static void x_draw_image_foreground (struct glyph_string *);
816 static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
817 static void x_clear_glyph_string_rect (struct glyph_string *, int,
818 int, int, int);
819 static void x_draw_relief_rect (struct frame *, int, int, int, int,
820 int, bool, bool, bool, bool, bool,
821 XRectangle *);
822 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
823 int, bool, bool, XRectangle *);
824 static void x_scroll_bar_clear (struct frame *);
825
826 #ifdef GLYPH_DEBUG
827 static void x_check_font (struct frame *, struct font *);
828 #endif
829
830
831 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
832 face. */
833
834 static void
835 x_set_cursor_gc (struct glyph_string *s)
836 {
837 if (s->font == FRAME_FONT (s->f)
838 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
839 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
840 && !s->cmp)
841 s->gc = s->f->output_data.x->cursor_gc;
842 else
843 {
844 /* Cursor on non-default face: must merge. */
845 XGCValues xgcv;
846 unsigned long mask;
847
848 xgcv.background = s->f->output_data.x->cursor_pixel;
849 xgcv.foreground = s->face->background;
850
851 /* If the glyph would be invisible, try a different foreground. */
852 if (xgcv.foreground == xgcv.background)
853 xgcv.foreground = s->face->foreground;
854 if (xgcv.foreground == xgcv.background)
855 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
856 if (xgcv.foreground == xgcv.background)
857 xgcv.foreground = s->face->foreground;
858
859 /* Make sure the cursor is distinct from text in this face. */
860 if (xgcv.background == s->face->background
861 && xgcv.foreground == s->face->foreground)
862 {
863 xgcv.background = s->face->foreground;
864 xgcv.foreground = s->face->background;
865 }
866
867 IF_DEBUG (x_check_font (s->f, s->font));
868 xgcv.graphics_exposures = False;
869 mask = GCForeground | GCBackground | GCGraphicsExposures;
870
871 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
872 XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
873 mask, &xgcv);
874 else
875 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
876 = XCreateGC (s->display, s->window, mask, &xgcv);
877
878 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
879 }
880 }
881
882
883 /* Set up S->gc of glyph string S for drawing text in mouse face. */
884
885 static void
886 x_set_mouse_face_gc (struct glyph_string *s)
887 {
888 int face_id;
889 struct face *face;
890
891 /* What face has to be used last for the mouse face? */
892 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
893 face = FACE_FROM_ID (s->f, face_id);
894 if (face == NULL)
895 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
896
897 if (s->first_glyph->type == CHAR_GLYPH)
898 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
899 else
900 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
901 s->face = FACE_FROM_ID (s->f, face_id);
902 prepare_face_for_display (s->f, s->face);
903
904 if (s->font == s->face->font)
905 s->gc = s->face->gc;
906 else
907 {
908 /* Otherwise construct scratch_cursor_gc with values from FACE
909 except for FONT. */
910 XGCValues xgcv;
911 unsigned long mask;
912
913 xgcv.background = s->face->background;
914 xgcv.foreground = s->face->foreground;
915 xgcv.graphics_exposures = False;
916 mask = GCForeground | GCBackground | GCGraphicsExposures;
917
918 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
919 XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
920 mask, &xgcv);
921 else
922 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
923 = XCreateGC (s->display, s->window, mask, &xgcv);
924
925 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
926
927 }
928 eassert (s->gc != 0);
929 }
930
931
932 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
933 Faces to use in the mode line have already been computed when the
934 matrix was built, so there isn't much to do, here. */
935
936 static void
937 x_set_mode_line_face_gc (struct glyph_string *s)
938 {
939 s->gc = s->face->gc;
940 }
941
942
943 /* Set S->gc of glyph string S for drawing that glyph string. Set
944 S->stippled_p to a non-zero value if the face of S has a stipple
945 pattern. */
946
947 static void
948 x_set_glyph_string_gc (struct glyph_string *s)
949 {
950 prepare_face_for_display (s->f, s->face);
951
952 if (s->hl == DRAW_NORMAL_TEXT)
953 {
954 s->gc = s->face->gc;
955 s->stippled_p = s->face->stipple != 0;
956 }
957 else if (s->hl == DRAW_INVERSE_VIDEO)
958 {
959 x_set_mode_line_face_gc (s);
960 s->stippled_p = s->face->stipple != 0;
961 }
962 else if (s->hl == DRAW_CURSOR)
963 {
964 x_set_cursor_gc (s);
965 s->stippled_p = false;
966 }
967 else if (s->hl == DRAW_MOUSE_FACE)
968 {
969 x_set_mouse_face_gc (s);
970 s->stippled_p = s->face->stipple != 0;
971 }
972 else if (s->hl == DRAW_IMAGE_RAISED
973 || s->hl == DRAW_IMAGE_SUNKEN)
974 {
975 s->gc = s->face->gc;
976 s->stippled_p = s->face->stipple != 0;
977 }
978 else
979 emacs_abort ();
980
981 /* GC must have been set. */
982 eassert (s->gc != 0);
983 }
984
985
986 /* Set clipping for output of glyph string S. S may be part of a mode
987 line or menu if we don't have X toolkit support. */
988
989 static void
990 x_set_glyph_string_clipping (struct glyph_string *s)
991 {
992 XRectangle *r = s->clip;
993 int n = get_glyph_string_clip_rects (s, r, 2);
994
995 if (n > 0)
996 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
997 s->num_clips = n;
998 }
999
1000
1001 /* Set SRC's clipping for output of glyph string DST. This is called
1002 when we are drawing DST's left_overhang or right_overhang only in
1003 the area of SRC. */
1004
1005 static void
1006 x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst)
1007 {
1008 XRectangle r;
1009
1010 r.x = src->x;
1011 r.width = src->width;
1012 r.y = src->y;
1013 r.height = src->height;
1014 dst->clip[0] = r;
1015 dst->num_clips = 1;
1016 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
1017 }
1018
1019
1020 /* RIF:
1021 Compute left and right overhang of glyph string S. */
1022
1023 static void
1024 x_compute_glyph_string_overhangs (struct glyph_string *s)
1025 {
1026 if (s->cmp == NULL
1027 && (s->first_glyph->type == CHAR_GLYPH
1028 || s->first_glyph->type == COMPOSITE_GLYPH))
1029 {
1030 struct font_metrics metrics;
1031
1032 if (s->first_glyph->type == CHAR_GLYPH)
1033 {
1034 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1035 struct font *font = s->font;
1036 int i;
1037
1038 for (i = 0; i < s->nchars; i++)
1039 code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
1040 font->driver->text_extents (font, code, s->nchars, &metrics);
1041 }
1042 else
1043 {
1044 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1045
1046 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
1047 }
1048 s->right_overhang = (metrics.rbearing > metrics.width
1049 ? metrics.rbearing - metrics.width : 0);
1050 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
1051 }
1052 else if (s->cmp)
1053 {
1054 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1055 s->left_overhang = - s->cmp->lbearing;
1056 }
1057 }
1058
1059
1060 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1061
1062 static void
1063 x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1064 {
1065 XGCValues xgcv;
1066 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1067 XSetForeground (s->display, s->gc, xgcv.background);
1068 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
1069 XSetForeground (s->display, s->gc, xgcv.foreground);
1070 }
1071
1072
1073 /* Draw the background of glyph_string S. If S->background_filled_p
1074 is non-zero don't draw it. FORCE_P non-zero means draw the
1075 background even if it wouldn't be drawn normally. This is used
1076 when a string preceding S draws into the background of S, or S
1077 contains the first component of a composition. */
1078
1079 static void
1080 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1081 {
1082 /* Nothing to do if background has already been drawn or if it
1083 shouldn't be drawn in the first place. */
1084 if (!s->background_filled_p)
1085 {
1086 int box_line_width = max (s->face->box_line_width, 0);
1087
1088 if (s->stippled_p)
1089 {
1090 /* Fill background with a stipple pattern. */
1091 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1092 XFillRectangle (s->display, s->window, s->gc, s->x,
1093 s->y + box_line_width,
1094 s->background_width,
1095 s->height - 2 * box_line_width);
1096 XSetFillStyle (s->display, s->gc, FillSolid);
1097 s->background_filled_p = true;
1098 }
1099 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1100 || s->font_not_found_p
1101 || s->extends_to_end_of_line_p
1102 || force_p)
1103 {
1104 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1105 s->background_width,
1106 s->height - 2 * box_line_width);
1107 s->background_filled_p = true;
1108 }
1109 }
1110 }
1111
1112
1113 /* Draw the foreground of glyph string S. */
1114
1115 static void
1116 x_draw_glyph_string_foreground (struct glyph_string *s)
1117 {
1118 int i, x;
1119
1120 /* If first glyph of S has a left box line, start drawing the text
1121 of S to the right of that box line. */
1122 if (s->face->box != FACE_NO_BOX
1123 && s->first_glyph->left_box_line_p)
1124 x = s->x + eabs (s->face->box_line_width);
1125 else
1126 x = s->x;
1127
1128 /* Draw characters of S as rectangles if S's font could not be
1129 loaded. */
1130 if (s->font_not_found_p)
1131 {
1132 for (i = 0; i < s->nchars; ++i)
1133 {
1134 struct glyph *g = s->first_glyph + i;
1135 XDrawRectangle (s->display, s->window,
1136 s->gc, x, s->y, g->pixel_width - 1,
1137 s->height - 1);
1138 x += g->pixel_width;
1139 }
1140 }
1141 else
1142 {
1143 struct font *font = s->font;
1144 int boff = font->baseline_offset;
1145 int y;
1146
1147 if (font->vertical_centering)
1148 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1149
1150 y = s->ybase - boff;
1151 if (s->for_overlaps
1152 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1153 font->driver->draw (s, 0, s->nchars, x, y, false);
1154 else
1155 font->driver->draw (s, 0, s->nchars, x, y, true);
1156 if (s->face->overstrike)
1157 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
1158 }
1159 }
1160
1161 /* Draw the foreground of composite glyph string S. */
1162
1163 static void
1164 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1165 {
1166 int i, j, x;
1167 struct font *font = s->font;
1168
1169 /* If first glyph of S has a left box line, start drawing the text
1170 of S to the right of that box line. */
1171 if (s->face && s->face->box != FACE_NO_BOX
1172 && s->first_glyph->left_box_line_p)
1173 x = s->x + eabs (s->face->box_line_width);
1174 else
1175 x = s->x;
1176
1177 /* S is a glyph string for a composition. S->cmp_from is the index
1178 of the first character drawn for glyphs of this composition.
1179 S->cmp_from == 0 means we are drawing the very first character of
1180 this composition. */
1181
1182 /* Draw a rectangle for the composition if the font for the very
1183 first character of the composition could not be loaded. */
1184 if (s->font_not_found_p)
1185 {
1186 if (s->cmp_from == 0)
1187 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
1188 s->width - 1, s->height - 1);
1189 }
1190 else if (! s->first_glyph->u.cmp.automatic)
1191 {
1192 int y = s->ybase;
1193
1194 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1195 /* TAB in a composition means display glyphs with padding
1196 space on the left or right. */
1197 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1198 {
1199 int xx = x + s->cmp->offsets[j * 2];
1200 int yy = y - s->cmp->offsets[j * 2 + 1];
1201
1202 font->driver->draw (s, j, j + 1, xx, yy, false);
1203 if (s->face->overstrike)
1204 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1205 }
1206 }
1207 else
1208 {
1209 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1210 Lisp_Object glyph;
1211 int y = s->ybase;
1212 int width = 0;
1213
1214 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1215 {
1216 glyph = LGSTRING_GLYPH (gstring, i);
1217 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1218 width += LGLYPH_WIDTH (glyph);
1219 else
1220 {
1221 int xoff, yoff, wadjust;
1222
1223 if (j < i)
1224 {
1225 font->driver->draw (s, j, i, x, y, false);
1226 if (s->face->overstrike)
1227 font->driver->draw (s, j, i, x + 1, y, false);
1228 x += width;
1229 }
1230 xoff = LGLYPH_XOFF (glyph);
1231 yoff = LGLYPH_YOFF (glyph);
1232 wadjust = LGLYPH_WADJUST (glyph);
1233 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1234 if (s->face->overstrike)
1235 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1236 false);
1237 x += wadjust;
1238 j = i + 1;
1239 width = 0;
1240 }
1241 }
1242 if (j < i)
1243 {
1244 font->driver->draw (s, j, i, x, y, false);
1245 if (s->face->overstrike)
1246 font->driver->draw (s, j, i, x + 1, y, false);
1247 }
1248 }
1249 }
1250
1251
1252 /* Draw the foreground of glyph string S for glyphless characters. */
1253
1254 static void
1255 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1256 {
1257 struct glyph *glyph = s->first_glyph;
1258 XChar2b char2b[8];
1259 int x, i, j;
1260
1261 /* If first glyph of S has a left box line, start drawing the text
1262 of S to the right of that box line. */
1263 if (s->face && s->face->box != FACE_NO_BOX
1264 && s->first_glyph->left_box_line_p)
1265 x = s->x + eabs (s->face->box_line_width);
1266 else
1267 x = s->x;
1268
1269 s->char2b = char2b;
1270
1271 for (i = 0; i < s->nchars; i++, glyph++)
1272 {
1273 char buf[7], *str = NULL;
1274 int len = glyph->u.glyphless.len;
1275
1276 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1277 {
1278 if (len > 0
1279 && CHAR_TABLE_P (Vglyphless_char_display)
1280 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1281 >= 1))
1282 {
1283 Lisp_Object acronym
1284 = (! glyph->u.glyphless.for_no_font
1285 ? CHAR_TABLE_REF (Vglyphless_char_display,
1286 glyph->u.glyphless.ch)
1287 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1288 if (STRINGP (acronym))
1289 str = SSDATA (acronym);
1290 }
1291 }
1292 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1293 {
1294 sprintf (buf, "%0*X",
1295 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1296 glyph->u.glyphless.ch);
1297 str = buf;
1298 }
1299
1300 if (str)
1301 {
1302 int upper_len = (len + 1) / 2;
1303 unsigned code;
1304
1305 /* It is assured that all LEN characters in STR is ASCII. */
1306 for (j = 0; j < len; j++)
1307 {
1308 code = s->font->driver->encode_char (s->font, str[j]);
1309 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1310 }
1311 s->font->driver->draw (s, 0, upper_len,
1312 x + glyph->slice.glyphless.upper_xoff,
1313 s->ybase + glyph->slice.glyphless.upper_yoff,
1314 false);
1315 s->font->driver->draw (s, upper_len, len,
1316 x + glyph->slice.glyphless.lower_xoff,
1317 s->ybase + glyph->slice.glyphless.lower_yoff,
1318 false);
1319 }
1320 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1321 XDrawRectangle (s->display, s->window, s->gc,
1322 x, s->ybase - glyph->ascent,
1323 glyph->pixel_width - 1,
1324 glyph->ascent + glyph->descent - 1);
1325 x += glyph->pixel_width;
1326 }
1327 }
1328
1329 #ifdef USE_X_TOOLKIT
1330
1331 #ifdef USE_LUCID
1332
1333 /* Return the frame on which widget WIDGET is used.. Abort if frame
1334 cannot be determined. */
1335
1336 static struct frame *
1337 x_frame_of_widget (Widget widget)
1338 {
1339 struct x_display_info *dpyinfo;
1340 Lisp_Object tail, frame;
1341 struct frame *f;
1342
1343 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1344
1345 /* Find the top-level shell of the widget. Note that this function
1346 can be called when the widget is not yet realized, so XtWindow
1347 (widget) == 0. That's the reason we can't simply use
1348 x_any_window_to_frame. */
1349 while (!XtIsTopLevelShell (widget))
1350 widget = XtParent (widget);
1351
1352 /* Look for a frame with that top-level widget. Allocate the color
1353 on that frame to get the right gamma correction value. */
1354 FOR_EACH_FRAME (tail, frame)
1355 {
1356 f = XFRAME (frame);
1357 if (FRAME_X_P (f)
1358 && f->output_data.nothing != 1
1359 && FRAME_DISPLAY_INFO (f) == dpyinfo
1360 && f->output_data.x->widget == widget)
1361 return f;
1362 }
1363 emacs_abort ();
1364 }
1365
1366 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1367 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1368 If this produces the same color as PIXEL, try a color where all RGB
1369 values have DELTA added. Return the allocated color in *PIXEL.
1370 DISPLAY is the X display, CMAP is the colormap to operate on.
1371 Value is true if successful. */
1372
1373 bool
1374 x_alloc_lighter_color_for_widget (Widget widget, Display *display, Colormap cmap,
1375 unsigned long *pixel, double factor, int delta)
1376 {
1377 struct frame *f = x_frame_of_widget (widget);
1378 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
1379 }
1380
1381 #endif /* USE_LUCID */
1382
1383
1384 /* Structure specifying which arguments should be passed by Xt to
1385 cvt_string_to_pixel. We want the widget's screen and colormap. */
1386
1387 static XtConvertArgRec cvt_string_to_pixel_args[] =
1388 {
1389 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
1390 sizeof (Screen *)},
1391 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
1392 sizeof (Colormap)}
1393 };
1394
1395
1396 /* The address of this variable is returned by
1397 cvt_string_to_pixel. */
1398
1399 static Pixel cvt_string_to_pixel_value;
1400
1401
1402 /* Convert a color name to a pixel color.
1403
1404 DPY is the display we are working on.
1405
1406 ARGS is an array of *NARGS XrmValue structures holding additional
1407 information about the widget for which the conversion takes place.
1408 The contents of this array are determined by the specification
1409 in cvt_string_to_pixel_args.
1410
1411 FROM is a pointer to an XrmValue which points to the color name to
1412 convert. TO is an XrmValue in which to return the pixel color.
1413
1414 CLOSURE_RET is a pointer to user-data, in which we record if
1415 we allocated the color or not.
1416
1417 Value is True if successful, False otherwise. */
1418
1419 static Boolean
1420 cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs,
1421 XrmValue *from, XrmValue *to,
1422 XtPointer *closure_ret)
1423 {
1424 Screen *screen;
1425 Colormap cmap;
1426 Pixel pixel;
1427 String color_name;
1428 XColor color;
1429
1430 if (*nargs != 2)
1431 {
1432 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1433 "wrongParameters", "cvt_string_to_pixel",
1434 "XtToolkitError",
1435 "Screen and colormap args required", NULL, NULL);
1436 return False;
1437 }
1438
1439 screen = *(Screen **) args[0].addr;
1440 cmap = *(Colormap *) args[1].addr;
1441 color_name = (String) from->addr;
1442
1443 if (strcmp (color_name, XtDefaultBackground) == 0)
1444 {
1445 *closure_ret = (XtPointer) False;
1446 pixel = WhitePixelOfScreen (screen);
1447 }
1448 else if (strcmp (color_name, XtDefaultForeground) == 0)
1449 {
1450 *closure_ret = (XtPointer) False;
1451 pixel = BlackPixelOfScreen (screen);
1452 }
1453 else if (XParseColor (dpy, cmap, color_name, &color)
1454 && x_alloc_nearest_color_1 (dpy, cmap, &color))
1455 {
1456 pixel = color.pixel;
1457 *closure_ret = (XtPointer) True;
1458 }
1459 else
1460 {
1461 String params[1];
1462 Cardinal nparams = 1;
1463
1464 params[0] = color_name;
1465 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1466 "badValue", "cvt_string_to_pixel",
1467 "XtToolkitError", "Invalid color `%s'",
1468 params, &nparams);
1469 return False;
1470 }
1471
1472 if (to->addr != NULL)
1473 {
1474 if (to->size < sizeof (Pixel))
1475 {
1476 to->size = sizeof (Pixel);
1477 return False;
1478 }
1479
1480 *(Pixel *) to->addr = pixel;
1481 }
1482 else
1483 {
1484 cvt_string_to_pixel_value = pixel;
1485 to->addr = (XtPointer) &cvt_string_to_pixel_value;
1486 }
1487
1488 to->size = sizeof (Pixel);
1489 return True;
1490 }
1491
1492
1493 /* Free a pixel color which was previously allocated via
1494 cvt_string_to_pixel. This is registered as the destructor
1495 for this type of resource via XtSetTypeConverter.
1496
1497 APP is the application context in which we work.
1498
1499 TO is a pointer to an XrmValue holding the color to free.
1500 CLOSURE is the value we stored in CLOSURE_RET for this color
1501 in cvt_string_to_pixel.
1502
1503 ARGS and NARGS are like for cvt_string_to_pixel. */
1504
1505 static void
1506 cvt_pixel_dtor (XtAppContext app, XrmValuePtr to, XtPointer closure, XrmValuePtr args,
1507 Cardinal *nargs)
1508 {
1509 if (*nargs != 2)
1510 {
1511 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
1512 "XtToolkitError",
1513 "Screen and colormap arguments required",
1514 NULL, NULL);
1515 }
1516 else if (closure != NULL)
1517 {
1518 /* We did allocate the pixel, so free it. */
1519 Screen *screen = *(Screen **) args[0].addr;
1520 Colormap cmap = *(Colormap *) args[1].addr;
1521 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
1522 (Pixel *) to->addr, 1);
1523 }
1524 }
1525
1526
1527 #endif /* USE_X_TOOLKIT */
1528
1529
1530 /* Value is an array of XColor structures for the contents of the
1531 color map of display DPY. Set *NCELLS to the size of the array.
1532 Note that this probably shouldn't be called for large color maps,
1533 say a 24-bit TrueColor map. */
1534
1535 static const XColor *
1536 x_color_cells (Display *dpy, int *ncells)
1537 {
1538 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1539
1540 if (dpyinfo->color_cells == NULL)
1541 {
1542 Screen *screen = dpyinfo->screen;
1543 int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1544 int i;
1545
1546 dpyinfo->color_cells = xnmalloc (ncolor_cells,
1547 sizeof *dpyinfo->color_cells);
1548 dpyinfo->ncolor_cells = ncolor_cells;
1549
1550 for (i = 0; i < ncolor_cells; ++i)
1551 dpyinfo->color_cells[i].pixel = i;
1552
1553 XQueryColors (dpy, dpyinfo->cmap,
1554 dpyinfo->color_cells, ncolor_cells);
1555 }
1556
1557 *ncells = dpyinfo->ncolor_cells;
1558 return dpyinfo->color_cells;
1559 }
1560
1561
1562 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1563 colors in COLORS. Use cached information, if available. */
1564
1565 void
1566 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1567 {
1568 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1569
1570 if (dpyinfo->color_cells)
1571 {
1572 int i;
1573 for (i = 0; i < ncolors; ++i)
1574 {
1575 unsigned long pixel = colors[i].pixel;
1576 eassert (pixel < dpyinfo->ncolor_cells);
1577 eassert (dpyinfo->color_cells[pixel].pixel == pixel);
1578 colors[i] = dpyinfo->color_cells[pixel];
1579 }
1580 }
1581 else
1582 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
1583 }
1584
1585
1586 /* On frame F, translate pixel color to RGB values for the color in
1587 COLOR. Use cached information, if available. */
1588
1589 void
1590 x_query_color (struct frame *f, XColor *color)
1591 {
1592 x_query_colors (f, color, 1);
1593 }
1594
1595
1596 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
1597 exact match can't be allocated, try the nearest color available.
1598 Value is true if successful. Set *COLOR to the color
1599 allocated. */
1600
1601 static bool
1602 x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
1603 {
1604 bool rc;
1605
1606 rc = XAllocColor (dpy, cmap, color) != 0;
1607 if (rc == 0)
1608 {
1609 /* If we got to this point, the colormap is full, so we're going
1610 to try to get the next closest color. The algorithm used is
1611 a least-squares matching, which is what X uses for closest
1612 color matching with StaticColor visuals. */
1613 int nearest, i;
1614 int max_color_delta = 255;
1615 int max_delta = 3 * max_color_delta;
1616 int nearest_delta = max_delta + 1;
1617 int ncells;
1618 const XColor *cells = x_color_cells (dpy, &ncells);
1619
1620 for (nearest = i = 0; i < ncells; ++i)
1621 {
1622 int dred = (color->red >> 8) - (cells[i].red >> 8);
1623 int dgreen = (color->green >> 8) - (cells[i].green >> 8);
1624 int dblue = (color->blue >> 8) - (cells[i].blue >> 8);
1625 int delta = dred * dred + dgreen * dgreen + dblue * dblue;
1626
1627 if (delta < nearest_delta)
1628 {
1629 nearest = i;
1630 nearest_delta = delta;
1631 }
1632 }
1633
1634 color->red = cells[nearest].red;
1635 color->green = cells[nearest].green;
1636 color->blue = cells[nearest].blue;
1637 rc = XAllocColor (dpy, cmap, color) != 0;
1638 }
1639 else
1640 {
1641 /* If allocation succeeded, and the allocated pixel color is not
1642 equal to a cached pixel color recorded earlier, there was a
1643 change in the colormap, so clear the color cache. */
1644 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1645 XColor *cached_color;
1646
1647 if (dpyinfo->color_cells
1648 && (cached_color = &dpyinfo->color_cells[color->pixel],
1649 (cached_color->red != color->red
1650 || cached_color->blue != color->blue
1651 || cached_color->green != color->green)))
1652 {
1653 xfree (dpyinfo->color_cells);
1654 dpyinfo->color_cells = NULL;
1655 dpyinfo->ncolor_cells = 0;
1656 }
1657 }
1658
1659 #ifdef DEBUG_X_COLORS
1660 if (rc)
1661 register_color (color->pixel);
1662 #endif /* DEBUG_X_COLORS */
1663
1664 return rc;
1665 }
1666
1667
1668 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
1669 exact match can't be allocated, try the nearest color available.
1670 Value is true if successful. Set *COLOR to the color
1671 allocated. */
1672
1673 bool
1674 x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
1675 {
1676 gamma_correct (f, color);
1677 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
1678 }
1679
1680
1681 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
1682 It's necessary to do this instead of just using PIXEL directly to
1683 get color reference counts right. */
1684
1685 unsigned long
1686 x_copy_color (struct frame *f, unsigned long pixel)
1687 {
1688 XColor color;
1689
1690 color.pixel = pixel;
1691 block_input ();
1692 x_query_color (f, &color);
1693 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
1694 unblock_input ();
1695 #ifdef DEBUG_X_COLORS
1696 register_color (pixel);
1697 #endif
1698 return color.pixel;
1699 }
1700
1701
1702 /* Brightness beyond which a color won't have its highlight brightness
1703 boosted.
1704
1705 Nominally, highlight colors for `3d' faces are calculated by
1706 brightening an object's color by a constant scale factor, but this
1707 doesn't yield good results for dark colors, so for colors who's
1708 brightness is less than this value (on a scale of 0-65535) have an
1709 use an additional additive factor.
1710
1711 The value here is set so that the default menu-bar/mode-line color
1712 (grey75) will not have its highlights changed at all. */
1713 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
1714
1715
1716 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
1717 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1718 If this produces the same color as PIXEL, try a color where all RGB
1719 values have DELTA added. Return the allocated color in *PIXEL.
1720 DISPLAY is the X display, CMAP is the colormap to operate on.
1721 Value is non-zero if successful. */
1722
1723 static bool
1724 x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
1725 unsigned long *pixel, double factor, int delta)
1726 {
1727 XColor color, new;
1728 long bright;
1729 bool success_p;
1730
1731 /* Get RGB color values. */
1732 color.pixel = *pixel;
1733 x_query_color (f, &color);
1734
1735 /* Change RGB values by specified FACTOR. Avoid overflow! */
1736 eassert (factor >= 0);
1737 new.red = min (0xffff, factor * color.red);
1738 new.green = min (0xffff, factor * color.green);
1739 new.blue = min (0xffff, factor * color.blue);
1740
1741 /* Calculate brightness of COLOR. */
1742 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
1743
1744 /* We only boost colors that are darker than
1745 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1746 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1747 /* Make an additive adjustment to NEW, because it's dark enough so
1748 that scaling by FACTOR alone isn't enough. */
1749 {
1750 /* How far below the limit this color is (0 - 1, 1 being darker). */
1751 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1752 /* The additive adjustment. */
1753 int min_delta = delta * dimness * factor / 2;
1754
1755 if (factor < 1)
1756 {
1757 new.red = max (0, new.red - min_delta);
1758 new.green = max (0, new.green - min_delta);
1759 new.blue = max (0, new.blue - min_delta);
1760 }
1761 else
1762 {
1763 new.red = min (0xffff, min_delta + new.red);
1764 new.green = min (0xffff, min_delta + new.green);
1765 new.blue = min (0xffff, min_delta + new.blue);
1766 }
1767 }
1768
1769 /* Try to allocate the color. */
1770 success_p = x_alloc_nearest_color (f, cmap, &new);
1771 if (success_p)
1772 {
1773 if (new.pixel == *pixel)
1774 {
1775 /* If we end up with the same color as before, try adding
1776 delta to the RGB values. */
1777 x_free_colors (f, &new.pixel, 1);
1778
1779 new.red = min (0xffff, delta + color.red);
1780 new.green = min (0xffff, delta + color.green);
1781 new.blue = min (0xffff, delta + color.blue);
1782 success_p = x_alloc_nearest_color (f, cmap, &new);
1783 }
1784 else
1785 success_p = true;
1786 *pixel = new.pixel;
1787 }
1788
1789 return success_p;
1790 }
1791
1792
1793 /* Set up the foreground color for drawing relief lines of glyph
1794 string S. RELIEF is a pointer to a struct relief containing the GC
1795 with which lines will be drawn. Use a color that is FACTOR or
1796 DELTA lighter or darker than the relief's background which is found
1797 in S->f->output_data.x->relief_background. If such a color cannot
1798 be allocated, use DEFAULT_PIXEL, instead. */
1799
1800 static void
1801 x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
1802 int delta, unsigned long default_pixel)
1803 {
1804 XGCValues xgcv;
1805 struct x_output *di = f->output_data.x;
1806 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
1807 unsigned long pixel;
1808 unsigned long background = di->relief_background;
1809 Colormap cmap = FRAME_X_COLORMAP (f);
1810 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1811 Display *dpy = FRAME_X_DISPLAY (f);
1812
1813 xgcv.graphics_exposures = False;
1814 xgcv.line_width = 1;
1815
1816 /* Free previously allocated color. The color cell will be reused
1817 when it has been freed as many times as it was allocated, so this
1818 doesn't affect faces using the same colors. */
1819 if (relief->gc && relief->pixel != -1)
1820 {
1821 x_free_colors (f, &relief->pixel, 1);
1822 relief->pixel = -1;
1823 }
1824
1825 /* Allocate new color. */
1826 xgcv.foreground = default_pixel;
1827 pixel = background;
1828 if (dpyinfo->n_planes != 1
1829 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
1830 xgcv.foreground = relief->pixel = pixel;
1831
1832 if (relief->gc == 0)
1833 {
1834 xgcv.stipple = dpyinfo->gray;
1835 mask |= GCStipple;
1836 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
1837 }
1838 else
1839 XChangeGC (dpy, relief->gc, mask, &xgcv);
1840 }
1841
1842
1843 /* Set up colors for the relief lines around glyph string S. */
1844
1845 static void
1846 x_setup_relief_colors (struct glyph_string *s)
1847 {
1848 struct x_output *di = s->f->output_data.x;
1849 unsigned long color;
1850
1851 if (s->face->use_box_color_for_shadows_p)
1852 color = s->face->box_color;
1853 else if (s->first_glyph->type == IMAGE_GLYPH
1854 && s->img->pixmap
1855 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1856 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1857 else
1858 {
1859 XGCValues xgcv;
1860
1861 /* Get the background color of the face. */
1862 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
1863 color = xgcv.background;
1864 }
1865
1866 if (di->white_relief.gc == 0
1867 || color != di->relief_background)
1868 {
1869 di->relief_background = color;
1870 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1871 WHITE_PIX_DEFAULT (s->f));
1872 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1873 BLACK_PIX_DEFAULT (s->f));
1874 }
1875 }
1876
1877
1878 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1879 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1880 to draw, it must be >= 0. RAISED_P means draw a raised
1881 relief. LEFT_P means draw a relief on the left side of
1882 the rectangle. RIGHT_P means draw a relief on the right
1883 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1884 when drawing. */
1885
1886 static void
1887 x_draw_relief_rect (struct frame *f,
1888 int left_x, int top_y, int right_x, int bottom_y,
1889 int width, bool raised_p, bool top_p, bool bot_p,
1890 bool left_p, bool right_p,
1891 XRectangle *clip_rect)
1892 {
1893 Display *dpy = FRAME_X_DISPLAY (f);
1894 Window window = FRAME_X_WINDOW (f);
1895 int i;
1896 GC gc;
1897
1898 if (raised_p)
1899 gc = f->output_data.x->white_relief.gc;
1900 else
1901 gc = f->output_data.x->black_relief.gc;
1902 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
1903
1904 /* This code is more complicated than it has to be, because of two
1905 minor hacks to make the boxes look nicer: (i) if width > 1, draw
1906 the outermost line using the black relief. (ii) Omit the four
1907 corner pixels. */
1908
1909 /* Top. */
1910 if (top_p)
1911 {
1912 if (width == 1)
1913 XDrawLine (dpy, window, gc,
1914 left_x + left_p, top_y,
1915 right_x + !right_p, top_y);
1916
1917 for (i = 1; i < width; ++i)
1918 XDrawLine (dpy, window, gc,
1919 left_x + i * left_p, top_y + i,
1920 right_x + 1 - i * right_p, top_y + i);
1921 }
1922
1923 /* Left. */
1924 if (left_p)
1925 {
1926 if (width == 1)
1927 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
1928
1929 XClearArea (dpy, window, left_x, top_y, 1, 1, False);
1930 XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
1931
1932 for (i = (width > 1 ? 1 : 0); i < width; ++i)
1933 XDrawLine (dpy, window, gc,
1934 left_x + i, top_y + (i + 1) * top_p,
1935 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
1936 }
1937
1938 XSetClipMask (dpy, gc, None);
1939 if (raised_p)
1940 gc = f->output_data.x->black_relief.gc;
1941 else
1942 gc = f->output_data.x->white_relief.gc;
1943 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
1944
1945 if (width > 1)
1946 {
1947 /* Outermost top line. */
1948 if (top_p)
1949 XDrawLine (dpy, window, gc,
1950 left_x + left_p, top_y,
1951 right_x + !right_p, top_y);
1952
1953 /* Outermost left line. */
1954 if (left_p)
1955 XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
1956 }
1957
1958 /* Bottom. */
1959 if (bot_p)
1960 {
1961 XDrawLine (dpy, window, gc,
1962 left_x + left_p, bottom_y,
1963 right_x + !right_p, bottom_y);
1964 for (i = 1; i < width; ++i)
1965 XDrawLine (dpy, window, gc,
1966 left_x + i * left_p, bottom_y - i,
1967 right_x + 1 - i * right_p, bottom_y - i);
1968 }
1969
1970 /* Right. */
1971 if (right_p)
1972 {
1973 XClearArea (dpy, window, right_x, top_y, 1, 1, False);
1974 XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
1975 for (i = 0; i < width; ++i)
1976 XDrawLine (dpy, window, gc,
1977 right_x - i, top_y + (i + 1) * top_p,
1978 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
1979 }
1980
1981 XSetClipMask (dpy, gc, None);
1982 }
1983
1984
1985 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1986 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1987 draw, it must be >= 0. LEFT_P means draw a line on the
1988 left side of the rectangle. RIGHT_P means draw a line
1989 on the right side of the rectangle. CLIP_RECT is the clipping
1990 rectangle to use when drawing. */
1991
1992 static void
1993 x_draw_box_rect (struct glyph_string *s,
1994 int left_x, int top_y, int right_x, int bottom_y, int width,
1995 bool left_p, bool right_p, XRectangle *clip_rect)
1996 {
1997 XGCValues xgcv;
1998
1999 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2000 XSetForeground (s->display, s->gc, s->face->box_color);
2001 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2002
2003 /* Top. */
2004 XFillRectangle (s->display, s->window, s->gc,
2005 left_x, top_y, right_x - left_x + 1, width);
2006
2007 /* Left. */
2008 if (left_p)
2009 XFillRectangle (s->display, s->window, s->gc,
2010 left_x, top_y, width, bottom_y - top_y + 1);
2011
2012 /* Bottom. */
2013 XFillRectangle (s->display, s->window, s->gc,
2014 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2015
2016 /* Right. */
2017 if (right_p)
2018 XFillRectangle (s->display, s->window, s->gc,
2019 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2020
2021 XSetForeground (s->display, s->gc, xgcv.foreground);
2022 XSetClipMask (s->display, s->gc, None);
2023 }
2024
2025
2026 /* Draw a box around glyph string S. */
2027
2028 static void
2029 x_draw_glyph_string_box (struct glyph_string *s)
2030 {
2031 int width, left_x, right_x, top_y, bottom_y, last_x;
2032 bool raised_p, left_p, right_p;
2033 struct glyph *last_glyph;
2034 XRectangle clip_rect;
2035
2036 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2037 ? WINDOW_RIGHT_EDGE_X (s->w)
2038 : window_box_right (s->w, s->area));
2039
2040 /* The glyph that may have a right box line. */
2041 last_glyph = (s->cmp || s->img
2042 ? s->first_glyph
2043 : s->first_glyph + s->nchars - 1);
2044
2045 width = eabs (s->face->box_line_width);
2046 raised_p = s->face->box == FACE_RAISED_BOX;
2047 left_x = s->x;
2048 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2049 ? last_x - 1
2050 : min (last_x, s->x + s->background_width) - 1);
2051 top_y = s->y;
2052 bottom_y = top_y + s->height - 1;
2053
2054 left_p = (s->first_glyph->left_box_line_p
2055 || (s->hl == DRAW_MOUSE_FACE
2056 && (s->prev == NULL
2057 || s->prev->hl != s->hl)));
2058 right_p = (last_glyph->right_box_line_p
2059 || (s->hl == DRAW_MOUSE_FACE
2060 && (s->next == NULL
2061 || s->next->hl != s->hl)));
2062
2063 get_glyph_string_clip_rect (s, &clip_rect);
2064
2065 if (s->face->box == FACE_SIMPLE_BOX)
2066 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2067 left_p, right_p, &clip_rect);
2068 else
2069 {
2070 x_setup_relief_colors (s);
2071 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2072 width, raised_p, true, true, left_p, right_p,
2073 &clip_rect);
2074 }
2075 }
2076
2077
2078 /* Draw foreground of image glyph string S. */
2079
2080 static void
2081 x_draw_image_foreground (struct glyph_string *s)
2082 {
2083 int x = s->x;
2084 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2085
2086 /* If first glyph of S has a left box line, start drawing it to the
2087 right of that line. */
2088 if (s->face->box != FACE_NO_BOX
2089 && s->first_glyph->left_box_line_p
2090 && s->slice.x == 0)
2091 x += eabs (s->face->box_line_width);
2092
2093 /* If there is a margin around the image, adjust x- and y-position
2094 by that margin. */
2095 if (s->slice.x == 0)
2096 x += s->img->hmargin;
2097 if (s->slice.y == 0)
2098 y += s->img->vmargin;
2099
2100 if (s->img->pixmap)
2101 {
2102 if (s->img->mask)
2103 {
2104 /* We can't set both a clip mask and use XSetClipRectangles
2105 because the latter also sets a clip mask. We also can't
2106 trust on the shape extension to be available
2107 (XShapeCombineRegion). So, compute the rectangle to draw
2108 manually. */
2109 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2110 | GCFunction);
2111 XGCValues xgcv;
2112 XRectangle clip_rect, image_rect, r;
2113
2114 xgcv.clip_mask = s->img->mask;
2115 xgcv.clip_x_origin = x;
2116 xgcv.clip_y_origin = y;
2117 xgcv.function = GXcopy;
2118 XChangeGC (s->display, s->gc, mask, &xgcv);
2119
2120 get_glyph_string_clip_rect (s, &clip_rect);
2121 image_rect.x = x;
2122 image_rect.y = y;
2123 image_rect.width = s->slice.width;
2124 image_rect.height = s->slice.height;
2125 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2126 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2127 s->slice.x + r.x - x, s->slice.y + r.y - y,
2128 r.width, r.height, r.x, r.y);
2129 }
2130 else
2131 {
2132 XRectangle clip_rect, image_rect, r;
2133
2134 get_glyph_string_clip_rect (s, &clip_rect);
2135 image_rect.x = x;
2136 image_rect.y = y;
2137 image_rect.width = s->slice.width;
2138 image_rect.height = s->slice.height;
2139 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2140 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2141 s->slice.x + r.x - x, s->slice.y + r.y - y,
2142 r.width, r.height, r.x, r.y);
2143
2144 /* When the image has a mask, we can expect that at
2145 least part of a mouse highlight or a block cursor will
2146 be visible. If the image doesn't have a mask, make
2147 a block cursor visible by drawing a rectangle around
2148 the image. I believe it's looking better if we do
2149 nothing here for mouse-face. */
2150 if (s->hl == DRAW_CURSOR)
2151 {
2152 int relief = eabs (s->img->relief);
2153 XDrawRectangle (s->display, s->window, s->gc,
2154 x - relief, y - relief,
2155 s->slice.width + relief*2 - 1,
2156 s->slice.height + relief*2 - 1);
2157 }
2158 }
2159 }
2160 else
2161 /* Draw a rectangle if image could not be loaded. */
2162 XDrawRectangle (s->display, s->window, s->gc, x, y,
2163 s->slice.width - 1, s->slice.height - 1);
2164 }
2165
2166
2167 /* Draw a relief around the image glyph string S. */
2168
2169 static void
2170 x_draw_image_relief (struct glyph_string *s)
2171 {
2172 int x1, y1, thick;
2173 bool raised_p, top_p, bot_p, left_p, right_p;
2174 int extra_x, extra_y;
2175 XRectangle r;
2176 int x = s->x;
2177 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2178
2179 /* If first glyph of S has a left box line, start drawing it to the
2180 right of that line. */
2181 if (s->face->box != FACE_NO_BOX
2182 && s->first_glyph->left_box_line_p
2183 && s->slice.x == 0)
2184 x += eabs (s->face->box_line_width);
2185
2186 /* If there is a margin around the image, adjust x- and y-position
2187 by that margin. */
2188 if (s->slice.x == 0)
2189 x += s->img->hmargin;
2190 if (s->slice.y == 0)
2191 y += s->img->vmargin;
2192
2193 if (s->hl == DRAW_IMAGE_SUNKEN
2194 || s->hl == DRAW_IMAGE_RAISED)
2195 {
2196 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2197 raised_p = s->hl == DRAW_IMAGE_RAISED;
2198 }
2199 else
2200 {
2201 thick = eabs (s->img->relief);
2202 raised_p = s->img->relief > 0;
2203 }
2204
2205 x1 = x + s->slice.width - 1;
2206 y1 = y + s->slice.height - 1;
2207
2208 extra_x = extra_y = 0;
2209 if (s->face->id == TOOL_BAR_FACE_ID)
2210 {
2211 if (CONSP (Vtool_bar_button_margin)
2212 && INTEGERP (XCAR (Vtool_bar_button_margin))
2213 && INTEGERP (XCDR (Vtool_bar_button_margin)))
2214 {
2215 extra_x = XINT (XCAR (Vtool_bar_button_margin));
2216 extra_y = XINT (XCDR (Vtool_bar_button_margin));
2217 }
2218 else if (INTEGERP (Vtool_bar_button_margin))
2219 extra_x = extra_y = XINT (Vtool_bar_button_margin);
2220 }
2221
2222 top_p = bot_p = left_p = right_p = false;
2223
2224 if (s->slice.x == 0)
2225 x -= thick + extra_x, left_p = true;
2226 if (s->slice.y == 0)
2227 y -= thick + extra_y, top_p = true;
2228 if (s->slice.x + s->slice.width == s->img->width)
2229 x1 += thick + extra_x, right_p = true;
2230 if (s->slice.y + s->slice.height == s->img->height)
2231 y1 += thick + extra_y, bot_p = true;
2232
2233 x_setup_relief_colors (s);
2234 get_glyph_string_clip_rect (s, &r);
2235 x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
2236 top_p, bot_p, left_p, right_p, &r);
2237 }
2238
2239
2240 /* Draw the foreground of image glyph string S to PIXMAP. */
2241
2242 static void
2243 x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2244 {
2245 int x = 0;
2246 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2247
2248 /* If first glyph of S has a left box line, start drawing it to the
2249 right of that line. */
2250 if (s->face->box != FACE_NO_BOX
2251 && s->first_glyph->left_box_line_p
2252 && s->slice.x == 0)
2253 x += eabs (s->face->box_line_width);
2254
2255 /* If there is a margin around the image, adjust x- and y-position
2256 by that margin. */
2257 if (s->slice.x == 0)
2258 x += s->img->hmargin;
2259 if (s->slice.y == 0)
2260 y += s->img->vmargin;
2261
2262 if (s->img->pixmap)
2263 {
2264 if (s->img->mask)
2265 {
2266 /* We can't set both a clip mask and use XSetClipRectangles
2267 because the latter also sets a clip mask. We also can't
2268 trust on the shape extension to be available
2269 (XShapeCombineRegion). So, compute the rectangle to draw
2270 manually. */
2271 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2272 | GCFunction);
2273 XGCValues xgcv;
2274
2275 xgcv.clip_mask = s->img->mask;
2276 xgcv.clip_x_origin = x - s->slice.x;
2277 xgcv.clip_y_origin = y - s->slice.y;
2278 xgcv.function = GXcopy;
2279 XChangeGC (s->display, s->gc, mask, &xgcv);
2280
2281 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2282 s->slice.x, s->slice.y,
2283 s->slice.width, s->slice.height, x, y);
2284 XSetClipMask (s->display, s->gc, None);
2285 }
2286 else
2287 {
2288 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2289 s->slice.x, s->slice.y,
2290 s->slice.width, s->slice.height, x, y);
2291
2292 /* When the image has a mask, we can expect that at
2293 least part of a mouse highlight or a block cursor will
2294 be visible. If the image doesn't have a mask, make
2295 a block cursor visible by drawing a rectangle around
2296 the image. I believe it's looking better if we do
2297 nothing here for mouse-face. */
2298 if (s->hl == DRAW_CURSOR)
2299 {
2300 int r = eabs (s->img->relief);
2301 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2302 s->slice.width + r*2 - 1,
2303 s->slice.height + r*2 - 1);
2304 }
2305 }
2306 }
2307 else
2308 /* Draw a rectangle if image could not be loaded. */
2309 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2310 s->slice.width - 1, s->slice.height - 1);
2311 }
2312
2313
2314 /* Draw part of the background of glyph string S. X, Y, W, and H
2315 give the rectangle to draw. */
2316
2317 static void
2318 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2319 {
2320 if (s->stippled_p)
2321 {
2322 /* Fill background with a stipple pattern. */
2323 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2324 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2325 XSetFillStyle (s->display, s->gc, FillSolid);
2326 }
2327 else
2328 x_clear_glyph_string_rect (s, x, y, w, h);
2329 }
2330
2331
2332 /* Draw image glyph string S.
2333
2334 s->y
2335 s->x +-------------------------
2336 | s->face->box
2337 |
2338 | +-------------------------
2339 | | s->img->margin
2340 | |
2341 | | +-------------------
2342 | | | the image
2343
2344 */
2345
2346 static void
2347 x_draw_image_glyph_string (struct glyph_string *s)
2348 {
2349 int box_line_hwidth = eabs (s->face->box_line_width);
2350 int box_line_vwidth = max (s->face->box_line_width, 0);
2351 int height;
2352 Pixmap pixmap = None;
2353
2354 height = s->height;
2355 if (s->slice.y == 0)
2356 height -= box_line_vwidth;
2357 if (s->slice.y + s->slice.height >= s->img->height)
2358 height -= box_line_vwidth;
2359
2360 /* Fill background with face under the image. Do it only if row is
2361 taller than image or if image has a clip mask to reduce
2362 flickering. */
2363 s->stippled_p = s->face->stipple != 0;
2364 if (height > s->slice.height
2365 || s->img->hmargin
2366 || s->img->vmargin
2367 || s->img->mask
2368 || s->img->pixmap == 0
2369 || s->width != s->background_width)
2370 {
2371 if (s->img->mask)
2372 {
2373 /* Create a pixmap as large as the glyph string. Fill it
2374 with the background color. Copy the image to it, using
2375 its mask. Copy the temporary pixmap to the display. */
2376 Screen *screen = FRAME_X_SCREEN (s->f);
2377 int depth = DefaultDepthOfScreen (screen);
2378
2379 /* Create a pixmap as large as the glyph string. */
2380 pixmap = XCreatePixmap (s->display, s->window,
2381 s->background_width,
2382 s->height, depth);
2383
2384 /* Don't clip in the following because we're working on the
2385 pixmap. */
2386 XSetClipMask (s->display, s->gc, None);
2387
2388 /* Fill the pixmap with the background color/stipple. */
2389 if (s->stippled_p)
2390 {
2391 /* Fill background with a stipple pattern. */
2392 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2393 XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
2394 XFillRectangle (s->display, pixmap, s->gc,
2395 0, 0, s->background_width, s->height);
2396 XSetFillStyle (s->display, s->gc, FillSolid);
2397 XSetTSOrigin (s->display, s->gc, 0, 0);
2398 }
2399 else
2400 {
2401 XGCValues xgcv;
2402 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2403 &xgcv);
2404 XSetForeground (s->display, s->gc, xgcv.background);
2405 XFillRectangle (s->display, pixmap, s->gc,
2406 0, 0, s->background_width, s->height);
2407 XSetForeground (s->display, s->gc, xgcv.foreground);
2408 }
2409 }
2410 else
2411 {
2412 int x = s->x;
2413 int y = s->y;
2414 int width = s->background_width;
2415
2416 if (s->first_glyph->left_box_line_p
2417 && s->slice.x == 0)
2418 {
2419 x += box_line_hwidth;
2420 width -= box_line_hwidth;
2421 }
2422
2423 if (s->slice.y == 0)
2424 y += box_line_vwidth;
2425
2426 x_draw_glyph_string_bg_rect (s, x, y, width, height);
2427 }
2428
2429 s->background_filled_p = true;
2430 }
2431
2432 /* Draw the foreground. */
2433 if (pixmap != None)
2434 {
2435 x_draw_image_foreground_1 (s, pixmap);
2436 x_set_glyph_string_clipping (s);
2437 XCopyArea (s->display, pixmap, s->window, s->gc,
2438 0, 0, s->background_width, s->height, s->x, s->y);
2439 XFreePixmap (s->display, pixmap);
2440 }
2441 else
2442 x_draw_image_foreground (s);
2443
2444 /* If we must draw a relief around the image, do it. */
2445 if (s->img->relief
2446 || s->hl == DRAW_IMAGE_RAISED
2447 || s->hl == DRAW_IMAGE_SUNKEN)
2448 x_draw_image_relief (s);
2449 }
2450
2451
2452 /* Draw stretch glyph string S. */
2453
2454 static void
2455 x_draw_stretch_glyph_string (struct glyph_string *s)
2456 {
2457 eassert (s->first_glyph->type == STRETCH_GLYPH);
2458
2459 if (s->hl == DRAW_CURSOR
2460 && !x_stretch_cursor_p)
2461 {
2462 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2463 wide as the stretch glyph. */
2464 int width, background_width = s->background_width;
2465 int x = s->x;
2466
2467 if (!s->row->reversed_p)
2468 {
2469 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2470
2471 if (x < left_x)
2472 {
2473 background_width -= left_x - x;
2474 x = left_x;
2475 }
2476 }
2477 else
2478 {
2479 /* In R2L rows, draw the cursor on the right edge of the
2480 stretch glyph. */
2481 int right_x = window_box_right (s->w, TEXT_AREA);
2482
2483 if (x + background_width > right_x)
2484 background_width -= x - right_x;
2485 x += background_width;
2486 }
2487 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2488 if (s->row->reversed_p)
2489 x -= width;
2490
2491 /* Draw cursor. */
2492 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2493
2494 /* Clear rest using the GC of the original non-cursor face. */
2495 if (width < background_width)
2496 {
2497 int y = s->y;
2498 int w = background_width - width, h = s->height;
2499 XRectangle r;
2500 GC gc;
2501
2502 if (!s->row->reversed_p)
2503 x += width;
2504 else
2505 x = s->x;
2506 if (s->row->mouse_face_p
2507 && cursor_in_mouse_face_p (s->w))
2508 {
2509 x_set_mouse_face_gc (s);
2510 gc = s->gc;
2511 }
2512 else
2513 gc = s->face->gc;
2514
2515 get_glyph_string_clip_rect (s, &r);
2516 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2517
2518 if (s->face->stipple)
2519 {
2520 /* Fill background with a stipple pattern. */
2521 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2522 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2523 XSetFillStyle (s->display, gc, FillSolid);
2524 }
2525 else
2526 {
2527 XGCValues xgcv;
2528 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2529 XSetForeground (s->display, gc, xgcv.background);
2530 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2531 XSetForeground (s->display, gc, xgcv.foreground);
2532 }
2533
2534 XSetClipMask (s->display, gc, None);
2535 }
2536 }
2537 else if (!s->background_filled_p)
2538 {
2539 int background_width = s->background_width;
2540 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2541
2542 /* Don't draw into left margin, fringe or scrollbar area
2543 except for header line and mode line. */
2544 if (x < left_x && !s->row->mode_line_p)
2545 {
2546 background_width -= left_x - x;
2547 x = left_x;
2548 }
2549 if (background_width > 0)
2550 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2551 }
2552
2553 s->background_filled_p = true;
2554 }
2555
2556 /*
2557 Draw a wavy line under S. The wave fills wave_height pixels from y0.
2558
2559 x0 wave_length = 2
2560 --
2561 y0 * * * * *
2562 |* * * * * * * * *
2563 wave_height = 3 | * * * *
2564
2565 */
2566
2567 static void
2568 x_draw_underwave (struct glyph_string *s)
2569 {
2570 int wave_height = 3, wave_length = 2;
2571 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
2572 bool odd;
2573 XRectangle wave_clip, string_clip, final_clip;
2574
2575 dx = wave_length;
2576 dy = wave_height - 1;
2577 x0 = s->x;
2578 y0 = s->ybase - wave_height + 3;
2579 width = s->width;
2580 xmax = x0 + width;
2581
2582 /* Find and set clipping rectangle */
2583
2584 wave_clip.x = x0;
2585 wave_clip.y = y0;
2586 wave_clip.width = width;
2587 wave_clip.height = wave_height;
2588 get_glyph_string_clip_rect (s, &string_clip);
2589
2590 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
2591 return;
2592
2593 XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
2594
2595 /* Draw the waves */
2596
2597 x1 = x0 - (x0 % dx);
2598 x2 = x1 + dx;
2599 odd = (x1 / dx) & 1;
2600 y1 = y2 = y0;
2601
2602 if (odd)
2603 y1 += dy;
2604 else
2605 y2 += dy;
2606
2607 if (INT_MAX - dx < xmax)
2608 emacs_abort ();
2609
2610 while (x1 <= xmax)
2611 {
2612 XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
2613 x1 = x2, y1 = y2;
2614 x2 += dx, y2 = y0 + odd*dy;
2615 odd = !odd;
2616 }
2617
2618 /* Restore previous clipping rectangle(s) */
2619 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
2620 }
2621
2622
2623 /* Draw glyph string S. */
2624
2625 static void
2626 x_draw_glyph_string (struct glyph_string *s)
2627 {
2628 bool relief_drawn_p = false;
2629
2630 /* If S draws into the background of its successors, draw the
2631 background of the successors first so that S can draw into it.
2632 This makes S->next use XDrawString instead of XDrawImageString. */
2633 if (s->next && s->right_overhang && !s->for_overlaps)
2634 {
2635 int width;
2636 struct glyph_string *next;
2637
2638 for (width = 0, next = s->next;
2639 next && width < s->right_overhang;
2640 width += next->width, next = next->next)
2641 if (next->first_glyph->type != IMAGE_GLYPH)
2642 {
2643 x_set_glyph_string_gc (next);
2644 x_set_glyph_string_clipping (next);
2645 if (next->first_glyph->type == STRETCH_GLYPH)
2646 x_draw_stretch_glyph_string (next);
2647 else
2648 x_draw_glyph_string_background (next, true);
2649 next->num_clips = 0;
2650 }
2651 }
2652
2653 /* Set up S->gc, set clipping and draw S. */
2654 x_set_glyph_string_gc (s);
2655
2656 /* Draw relief (if any) in advance for char/composition so that the
2657 glyph string can be drawn over it. */
2658 if (!s->for_overlaps
2659 && s->face->box != FACE_NO_BOX
2660 && (s->first_glyph->type == CHAR_GLYPH
2661 || s->first_glyph->type == COMPOSITE_GLYPH))
2662
2663 {
2664 x_set_glyph_string_clipping (s);
2665 x_draw_glyph_string_background (s, true);
2666 x_draw_glyph_string_box (s);
2667 x_set_glyph_string_clipping (s);
2668 relief_drawn_p = true;
2669 }
2670 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2671 && !s->clip_tail
2672 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2673 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2674 /* We must clip just this glyph. left_overhang part has already
2675 drawn when s->prev was drawn, and right_overhang part will be
2676 drawn later when s->next is drawn. */
2677 x_set_glyph_string_clipping_exactly (s, s);
2678 else
2679 x_set_glyph_string_clipping (s);
2680
2681 switch (s->first_glyph->type)
2682 {
2683 case IMAGE_GLYPH:
2684 x_draw_image_glyph_string (s);
2685 break;
2686
2687 case STRETCH_GLYPH:
2688 x_draw_stretch_glyph_string (s);
2689 break;
2690
2691 case CHAR_GLYPH:
2692 if (s->for_overlaps)
2693 s->background_filled_p = true;
2694 else
2695 x_draw_glyph_string_background (s, false);
2696 x_draw_glyph_string_foreground (s);
2697 break;
2698
2699 case COMPOSITE_GLYPH:
2700 if (s->for_overlaps || (s->cmp_from > 0
2701 && ! s->first_glyph->u.cmp.automatic))
2702 s->background_filled_p = true;
2703 else
2704 x_draw_glyph_string_background (s, true);
2705 x_draw_composite_glyph_string_foreground (s);
2706 break;
2707
2708 case GLYPHLESS_GLYPH:
2709 if (s->for_overlaps)
2710 s->background_filled_p = true;
2711 else
2712 x_draw_glyph_string_background (s, true);
2713 x_draw_glyphless_glyph_string_foreground (s);
2714 break;
2715
2716 default:
2717 emacs_abort ();
2718 }
2719
2720 if (!s->for_overlaps)
2721 {
2722 /* Draw underline. */
2723 if (s->face->underline_p)
2724 {
2725 if (s->face->underline_type == FACE_UNDER_WAVE)
2726 {
2727 if (s->face->underline_defaulted_p)
2728 x_draw_underwave (s);
2729 else
2730 {
2731 XGCValues xgcv;
2732 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2733 XSetForeground (s->display, s->gc, s->face->underline_color);
2734 x_draw_underwave (s);
2735 XSetForeground (s->display, s->gc, xgcv.foreground);
2736 }
2737 }
2738 else if (s->face->underline_type == FACE_UNDER_LINE)
2739 {
2740 unsigned long thickness, position;
2741 int y;
2742
2743 if (s->prev && s->prev->face->underline_p
2744 && s->prev->face->underline_type == FACE_UNDER_LINE)
2745 {
2746 /* We use the same underline style as the previous one. */
2747 thickness = s->prev->underline_thickness;
2748 position = s->prev->underline_position;
2749 }
2750 else
2751 {
2752 /* Get the underline thickness. Default is 1 pixel. */
2753 if (s->font && s->font->underline_thickness > 0)
2754 thickness = s->font->underline_thickness;
2755 else
2756 thickness = 1;
2757 if (x_underline_at_descent_line)
2758 position = (s->height - thickness) - (s->ybase - s->y);
2759 else
2760 {
2761 /* Get the underline position. This is the recommended
2762 vertical offset in pixels from the baseline to the top of
2763 the underline. This is a signed value according to the
2764 specs, and its default is
2765
2766 ROUND ((maximum descent) / 2), with
2767 ROUND(x) = floor (x + 0.5) */
2768
2769 if (x_use_underline_position_properties
2770 && s->font && s->font->underline_position >= 0)
2771 position = s->font->underline_position;
2772 else if (s->font)
2773 position = (s->font->descent + 1) / 2;
2774 else
2775 position = underline_minimum_offset;
2776 }
2777 position = max (position, underline_minimum_offset);
2778 }
2779 /* Check the sanity of thickness and position. We should
2780 avoid drawing underline out of the current line area. */
2781 if (s->y + s->height <= s->ybase + position)
2782 position = (s->height - 1) - (s->ybase - s->y);
2783 if (s->y + s->height < s->ybase + position + thickness)
2784 thickness = (s->y + s->height) - (s->ybase + position);
2785 s->underline_thickness = thickness;
2786 s->underline_position = position;
2787 y = s->ybase + position;
2788 if (s->face->underline_defaulted_p)
2789 XFillRectangle (s->display, s->window, s->gc,
2790 s->x, y, s->width, thickness);
2791 else
2792 {
2793 XGCValues xgcv;
2794 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2795 XSetForeground (s->display, s->gc, s->face->underline_color);
2796 XFillRectangle (s->display, s->window, s->gc,
2797 s->x, y, s->width, thickness);
2798 XSetForeground (s->display, s->gc, xgcv.foreground);
2799 }
2800 }
2801 }
2802 /* Draw overline. */
2803 if (s->face->overline_p)
2804 {
2805 unsigned long dy = 0, h = 1;
2806
2807 if (s->face->overline_color_defaulted_p)
2808 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2809 s->width, h);
2810 else
2811 {
2812 XGCValues xgcv;
2813 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2814 XSetForeground (s->display, s->gc, s->face->overline_color);
2815 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2816 s->width, h);
2817 XSetForeground (s->display, s->gc, xgcv.foreground);
2818 }
2819 }
2820
2821 /* Draw strike-through. */
2822 if (s->face->strike_through_p)
2823 {
2824 unsigned long h = 1;
2825 unsigned long dy = (s->height - h) / 2;
2826
2827 if (s->face->strike_through_color_defaulted_p)
2828 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2829 s->width, h);
2830 else
2831 {
2832 XGCValues xgcv;
2833 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2834 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2835 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2836 s->width, h);
2837 XSetForeground (s->display, s->gc, xgcv.foreground);
2838 }
2839 }
2840
2841 /* Draw relief if not yet drawn. */
2842 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2843 x_draw_glyph_string_box (s);
2844
2845 if (s->prev)
2846 {
2847 struct glyph_string *prev;
2848
2849 for (prev = s->prev; prev; prev = prev->prev)
2850 if (prev->hl != s->hl
2851 && prev->x + prev->width + prev->right_overhang > s->x)
2852 {
2853 /* As prev was drawn while clipped to its own area, we
2854 must draw the right_overhang part using s->hl now. */
2855 enum draw_glyphs_face save = prev->hl;
2856
2857 prev->hl = s->hl;
2858 x_set_glyph_string_gc (prev);
2859 x_set_glyph_string_clipping_exactly (s, prev);
2860 if (prev->first_glyph->type == CHAR_GLYPH)
2861 x_draw_glyph_string_foreground (prev);
2862 else
2863 x_draw_composite_glyph_string_foreground (prev);
2864 XSetClipMask (prev->display, prev->gc, None);
2865 prev->hl = save;
2866 prev->num_clips = 0;
2867 }
2868 }
2869
2870 if (s->next)
2871 {
2872 struct glyph_string *next;
2873
2874 for (next = s->next; next; next = next->next)
2875 if (next->hl != s->hl
2876 && next->x - next->left_overhang < s->x + s->width)
2877 {
2878 /* As next will be drawn while clipped to its own area,
2879 we must draw the left_overhang part using s->hl now. */
2880 enum draw_glyphs_face save = next->hl;
2881
2882 next->hl = s->hl;
2883 x_set_glyph_string_gc (next);
2884 x_set_glyph_string_clipping_exactly (s, next);
2885 if (next->first_glyph->type == CHAR_GLYPH)
2886 x_draw_glyph_string_foreground (next);
2887 else
2888 x_draw_composite_glyph_string_foreground (next);
2889 XSetClipMask (next->display, next->gc, None);
2890 next->hl = save;
2891 next->num_clips = 0;
2892 next->clip_head = s->next;
2893 }
2894 }
2895 }
2896
2897 /* Reset clipping. */
2898 XSetClipMask (s->display, s->gc, None);
2899 s->num_clips = 0;
2900 }
2901
2902 /* Shift display to make room for inserted glyphs. */
2903
2904 static void
2905 x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
2906 {
2907 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2908 f->output_data.x->normal_gc,
2909 x, y, width, height,
2910 x + shift_by, y);
2911 }
2912
2913 /* Delete N glyphs at the nominal cursor position. Not implemented
2914 for X frames. */
2915
2916 static void
2917 x_delete_glyphs (struct frame *f, register int n)
2918 {
2919 emacs_abort ();
2920 }
2921
2922
2923 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2924 If they are <= 0, this is probably an error. */
2925
2926 void
2927 x_clear_area (Display *dpy, Window window, int x, int y, int width, int height)
2928 {
2929 eassert (width > 0 && height > 0);
2930 XClearArea (dpy, window, x, y, width, height, False);
2931 }
2932
2933
2934 /* Clear an entire frame. */
2935
2936 static void
2937 x_clear_frame (struct frame *f)
2938 {
2939 /* Clearing the frame will erase any cursor, so mark them all as no
2940 longer visible. */
2941 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2942
2943 block_input ();
2944
2945 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
2946
2947 /* We have to clear the scroll bars. If we have changed colors or
2948 something like that, then they should be notified. */
2949 x_scroll_bar_clear (f);
2950
2951 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
2952 /* Make sure scroll bars are redrawn. As they aren't redrawn by
2953 redisplay, do it here. */
2954 if (FRAME_GTK_WIDGET (f))
2955 gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
2956 #endif
2957
2958 XFlush (FRAME_X_DISPLAY (f));
2959
2960 unblock_input ();
2961 }
2962
2963 /* RIF: Show hourglass cursor on frame F. */
2964
2965 static void
2966 x_show_hourglass (struct frame *f)
2967 {
2968 Display *dpy = FRAME_X_DISPLAY (f);
2969
2970 if (dpy)
2971 {
2972 struct x_output *x = FRAME_X_OUTPUT (f);
2973 #ifdef USE_X_TOOLKIT
2974 if (x->widget)
2975 #else
2976 if (FRAME_OUTER_WINDOW (f))
2977 #endif
2978 {
2979 x->hourglass_p = true;
2980
2981 if (!x->hourglass_window)
2982 {
2983 unsigned long mask = CWCursor;
2984 XSetWindowAttributes attrs;
2985 #ifdef USE_GTK
2986 Window parent = FRAME_X_WINDOW (f);
2987 #else
2988 Window parent = FRAME_OUTER_WINDOW (f);
2989 #endif
2990 attrs.cursor = x->hourglass_cursor;
2991
2992 x->hourglass_window = XCreateWindow
2993 (dpy, parent, 0, 0, 32000, 32000, 0, 0,
2994 InputOnly, CopyFromParent, mask, &attrs);
2995 }
2996
2997 XMapRaised (dpy, x->hourglass_window);
2998 XFlush (dpy);
2999 }
3000 }
3001 }
3002
3003 /* RIF: Cancel hourglass cursor on frame F. */
3004
3005 static void
3006 x_hide_hourglass (struct frame *f)
3007 {
3008 struct x_output *x = FRAME_X_OUTPUT (f);
3009
3010 /* Watch out for newly created frames. */
3011 if (x->hourglass_window)
3012 {
3013 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
3014 /* Sync here because XTread_socket looks at the
3015 hourglass_p flag that is reset to zero below. */
3016 XSync (FRAME_X_DISPLAY (f), False);
3017 x->hourglass_p = false;
3018 }
3019 }
3020
3021 /* Invert the middle quarter of the frame for .15 sec. */
3022
3023 static void
3024 XTflash (struct frame *f)
3025 {
3026 block_input ();
3027
3028 {
3029 #ifdef USE_GTK
3030 /* Use Gdk routines to draw. This way, we won't draw over scroll bars
3031 when the scroll bars and the edit widget share the same X window. */
3032 GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
3033 #ifdef HAVE_GTK3
3034 cairo_t *cr = gdk_cairo_create (window);
3035 cairo_set_source_rgb (cr, 1, 1, 1);
3036 cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
3037 #define XFillRectangle(d, win, gc, x, y, w, h) \
3038 do { \
3039 cairo_rectangle (cr, x, y, w, h); \
3040 cairo_fill (cr); \
3041 } \
3042 while (false)
3043 #else /* ! HAVE_GTK3 */
3044 GdkGCValues vals;
3045 GdkGC *gc;
3046 vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
3047 ^ FRAME_BACKGROUND_PIXEL (f));
3048 vals.function = GDK_XOR;
3049 gc = gdk_gc_new_with_values (window,
3050 &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
3051 #define XFillRectangle(d, win, gc, x, y, w, h) \
3052 gdk_draw_rectangle (window, gc, TRUE, x, y, w, h)
3053 #endif /* ! HAVE_GTK3 */
3054 #else /* ! USE_GTK */
3055 GC gc;
3056
3057 /* Create a GC that will use the GXxor function to flip foreground
3058 pixels into background pixels. */
3059 {
3060 XGCValues values;
3061
3062 values.function = GXxor;
3063 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
3064 ^ FRAME_BACKGROUND_PIXEL (f));
3065
3066 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3067 GCFunction | GCForeground, &values);
3068 }
3069 #endif
3070 {
3071 /* Get the height not including a menu bar widget. */
3072 int height = FRAME_PIXEL_HEIGHT (f);
3073 /* Height of each line to flash. */
3074 int flash_height = FRAME_LINE_HEIGHT (f);
3075 /* These will be the left and right margins of the rectangles. */
3076 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3077 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3078 int width = flash_right - flash_left;
3079
3080 /* If window is tall, flash top and bottom line. */
3081 if (height > 3 * FRAME_LINE_HEIGHT (f))
3082 {
3083 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3084 flash_left,
3085 (FRAME_INTERNAL_BORDER_WIDTH (f)
3086 + FRAME_TOP_MARGIN_HEIGHT (f)),
3087 width, flash_height);
3088 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3089 flash_left,
3090 (height - flash_height
3091 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3092 width, flash_height);
3093
3094 }
3095 else
3096 /* If it is short, flash it all. */
3097 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3098 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3099 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3100
3101 x_flush (f);
3102
3103 {
3104 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
3105 struct timespec wakeup = timespec_add (current_timespec (), delay);
3106
3107 /* Keep waiting until past the time wakeup or any input gets
3108 available. */
3109 while (! detect_input_pending ())
3110 {
3111 struct timespec current = current_timespec ();
3112 struct timespec timeout;
3113
3114 /* Break if result would not be positive. */
3115 if (timespec_cmp (wakeup, current) <= 0)
3116 break;
3117
3118 /* How long `select' should wait. */
3119 timeout = make_timespec (0, 10 * 1000 * 1000);
3120
3121 /* Try to wait that long--but we might wake up sooner. */
3122 pselect (0, NULL, NULL, NULL, &timeout, NULL);
3123 }
3124 }
3125
3126 /* If window is tall, flash top and bottom line. */
3127 if (height > 3 * FRAME_LINE_HEIGHT (f))
3128 {
3129 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3130 flash_left,
3131 (FRAME_INTERNAL_BORDER_WIDTH (f)
3132 + FRAME_TOP_MARGIN_HEIGHT (f)),
3133 width, flash_height);
3134 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3135 flash_left,
3136 (height - flash_height
3137 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3138 width, flash_height);
3139 }
3140 else
3141 /* If it is short, flash it all. */
3142 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3143 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3144 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3145
3146 #ifdef USE_GTK
3147 #ifdef HAVE_GTK3
3148 cairo_destroy (cr);
3149 #else
3150 g_object_unref (G_OBJECT (gc));
3151 #endif
3152 #undef XFillRectangle
3153 #else
3154 XFreeGC (FRAME_X_DISPLAY (f), gc);
3155 #endif
3156 x_flush (f);
3157 }
3158 }
3159
3160 unblock_input ();
3161 }
3162
3163
3164 static void
3165 XTtoggle_invisible_pointer (struct frame *f, bool invisible)
3166 {
3167 block_input ();
3168 FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
3169 unblock_input ();
3170 }
3171
3172
3173 /* Make audible bell. */
3174
3175 static void
3176 XTring_bell (struct frame *f)
3177 {
3178 if (FRAME_X_DISPLAY (f))
3179 {
3180 if (visible_bell)
3181 XTflash (f);
3182 else
3183 {
3184 block_input ();
3185 #ifdef HAVE_XKB
3186 XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
3187 #else
3188 XBell (FRAME_X_DISPLAY (f), 0);
3189 #endif
3190 XFlush (FRAME_X_DISPLAY (f));
3191 unblock_input ();
3192 }
3193 }
3194 }
3195
3196 /***********************************************************************
3197 Line Dance
3198 ***********************************************************************/
3199
3200 /* Perform an insert-lines or delete-lines operation, inserting N
3201 lines or deleting -N lines at vertical position VPOS. */
3202
3203 static void
3204 x_ins_del_lines (struct frame *f, int vpos, int n)
3205 {
3206 emacs_abort ();
3207 }
3208
3209
3210 /* Scroll part of the display as described by RUN. */
3211
3212 static void
3213 x_scroll_run (struct window *w, struct run *run)
3214 {
3215 struct frame *f = XFRAME (w->frame);
3216 int x, y, width, height, from_y, to_y, bottom_y;
3217
3218 /* Get frame-relative bounding box of the text display area of W,
3219 without mode lines. Include in this box the left and right
3220 fringe of W. */
3221 window_box (w, ANY_AREA, &x, &y, &width, &height);
3222
3223 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3224 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3225 bottom_y = y + height;
3226
3227 if (to_y < from_y)
3228 {
3229 /* Scrolling up. Make sure we don't copy part of the mode
3230 line at the bottom. */
3231 if (from_y + run->height > bottom_y)
3232 height = bottom_y - from_y;
3233 else
3234 height = run->height;
3235 }
3236 else
3237 {
3238 /* Scrolling down. Make sure we don't copy over the mode line.
3239 at the bottom. */
3240 if (to_y + run->height > bottom_y)
3241 height = bottom_y - to_y;
3242 else
3243 height = run->height;
3244 }
3245
3246 block_input ();
3247
3248 /* Cursor off. Will be switched on again in x_update_window_end. */
3249 x_clear_cursor (w);
3250
3251 XCopyArea (FRAME_X_DISPLAY (f),
3252 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3253 f->output_data.x->normal_gc,
3254 x, from_y,
3255 width, height,
3256 x, to_y);
3257
3258 unblock_input ();
3259 }
3260
3261
3262 \f
3263 /***********************************************************************
3264 Exposure Events
3265 ***********************************************************************/
3266
3267 \f
3268 static void
3269 frame_highlight (struct frame *f)
3270 {
3271 /* We used to only do this if Vx_no_window_manager was non-nil, but
3272 the ICCCM (section 4.1.6) says that the window's border pixmap
3273 and border pixel are window attributes which are "private to the
3274 client", so we can always change it to whatever we want. */
3275 block_input ();
3276 /* I recently started to get errors in this XSetWindowBorder, depending on
3277 the window-manager in use, tho something more is at play since I've been
3278 using that same window-manager binary for ever. Let's not crash just
3279 because of this (bug#9310). */
3280 x_catch_errors (FRAME_X_DISPLAY (f));
3281 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3282 f->output_data.x->border_pixel);
3283 x_uncatch_errors ();
3284 unblock_input ();
3285 x_update_cursor (f, true);
3286 x_set_frame_alpha (f);
3287 }
3288
3289 static void
3290 frame_unhighlight (struct frame *f)
3291 {
3292 /* We used to only do this if Vx_no_window_manager was non-nil, but
3293 the ICCCM (section 4.1.6) says that the window's border pixmap
3294 and border pixel are window attributes which are "private to the
3295 client", so we can always change it to whatever we want. */
3296 block_input ();
3297 /* Same as above for XSetWindowBorder (bug#9310). */
3298 x_catch_errors (FRAME_X_DISPLAY (f));
3299 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3300 f->output_data.x->border_tile);
3301 x_uncatch_errors ();
3302 unblock_input ();
3303 x_update_cursor (f, true);
3304 x_set_frame_alpha (f);
3305 }
3306
3307 /* The focus has changed. Update the frames as necessary to reflect
3308 the new situation. Note that we can't change the selected frame
3309 here, because the Lisp code we are interrupting might become confused.
3310 Each event gets marked with the frame in which it occurred, so the
3311 Lisp code can tell when the switch took place by examining the events. */
3312
3313 static void
3314 x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
3315 {
3316 struct frame *old_focus = dpyinfo->x_focus_frame;
3317
3318 if (frame != dpyinfo->x_focus_frame)
3319 {
3320 /* Set this before calling other routines, so that they see
3321 the correct value of x_focus_frame. */
3322 dpyinfo->x_focus_frame = frame;
3323
3324 if (old_focus && old_focus->auto_lower)
3325 x_lower_frame (old_focus);
3326
3327 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3328 dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
3329 else
3330 dpyinfo->x_pending_autoraise_frame = NULL;
3331 }
3332
3333 x_frame_rehighlight (dpyinfo);
3334 }
3335
3336 /* Handle FocusIn and FocusOut state changes for FRAME.
3337 If FRAME has focus and there exists more than one frame, puts
3338 a FOCUS_IN_EVENT into *BUFP. */
3339
3340 static void
3341 x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
3342 {
3343 if (type == FocusIn)
3344 {
3345 if (dpyinfo->x_focus_event_frame != frame)
3346 {
3347 x_new_focus_frame (dpyinfo, frame);
3348 dpyinfo->x_focus_event_frame = frame;
3349
3350 /* Don't stop displaying the initial startup message
3351 for a switch-frame event we don't need. */
3352 /* When run as a daemon, Vterminal_frame is always NIL. */
3353 bufp->arg = (((NILP (Vterminal_frame)
3354 || ! FRAME_X_P (XFRAME (Vterminal_frame))
3355 || EQ (Fdaemonp (), Qt))
3356 && CONSP (Vframe_list)
3357 && !NILP (XCDR (Vframe_list)))
3358 ? Qt : Qnil);
3359 bufp->kind = FOCUS_IN_EVENT;
3360 XSETFRAME (bufp->frame_or_window, frame);
3361 }
3362
3363 frame->output_data.x->focus_state |= state;
3364
3365 #ifdef HAVE_X_I18N
3366 if (FRAME_XIC (frame))
3367 XSetICFocus (FRAME_XIC (frame));
3368 #endif
3369 }
3370 else if (type == FocusOut)
3371 {
3372 frame->output_data.x->focus_state &= ~state;
3373
3374 if (dpyinfo->x_focus_event_frame == frame)
3375 {
3376 dpyinfo->x_focus_event_frame = 0;
3377 x_new_focus_frame (dpyinfo, 0);
3378
3379 bufp->kind = FOCUS_OUT_EVENT;
3380 XSETFRAME (bufp->frame_or_window, frame);
3381 }
3382
3383 #ifdef HAVE_X_I18N
3384 if (FRAME_XIC (frame))
3385 XUnsetICFocus (FRAME_XIC (frame));
3386 #endif
3387 if (frame->pointer_invisible)
3388 XTtoggle_invisible_pointer (frame, false);
3389 }
3390 }
3391
3392 /* Return the Emacs frame-object corresponding to an X window.
3393 It could be the frame's main window or an icon window. */
3394
3395 static struct frame *
3396 x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
3397 {
3398 Lisp_Object tail, frame;
3399 struct frame *f;
3400
3401 if (wdesc == None)
3402 return NULL;
3403
3404 FOR_EACH_FRAME (tail, frame)
3405 {
3406 f = XFRAME (frame);
3407 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
3408 continue;
3409 if (f->output_data.x->hourglass_window == wdesc)
3410 return f;
3411 #ifdef USE_X_TOOLKIT
3412 if ((f->output_data.x->edit_widget
3413 && XtWindow (f->output_data.x->edit_widget) == wdesc)
3414 /* A tooltip frame? */
3415 || (!f->output_data.x->edit_widget
3416 && FRAME_X_WINDOW (f) == wdesc)
3417 || f->output_data.x->icon_desc == wdesc)
3418 return f;
3419 #else /* not USE_X_TOOLKIT */
3420 #ifdef USE_GTK
3421 if (f->output_data.x->edit_widget)
3422 {
3423 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
3424 struct x_output *x = f->output_data.x;
3425 if (gwdesc != 0 && gwdesc == x->edit_widget)
3426 return f;
3427 }
3428 #endif /* USE_GTK */
3429 if (FRAME_X_WINDOW (f) == wdesc
3430 || f->output_data.x->icon_desc == wdesc)
3431 return f;
3432 #endif /* not USE_X_TOOLKIT */
3433 }
3434 return 0;
3435 }
3436
3437 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3438
3439 /* Like x_window_to_frame but also compares the window with the widget's
3440 windows. */
3441
3442 static struct frame *
3443 x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
3444 {
3445 Lisp_Object tail, frame;
3446 struct frame *f, *found = NULL;
3447 struct x_output *x;
3448
3449 if (wdesc == None)
3450 return NULL;
3451
3452 FOR_EACH_FRAME (tail, frame)
3453 {
3454 if (found)
3455 break;
3456 f = XFRAME (frame);
3457 if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
3458 {
3459 /* This frame matches if the window is any of its widgets. */
3460 x = f->output_data.x;
3461 if (x->hourglass_window == wdesc)
3462 found = f;
3463 else if (x->widget)
3464 {
3465 #ifdef USE_GTK
3466 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
3467 if (gwdesc != 0
3468 && gtk_widget_get_toplevel (gwdesc) == x->widget)
3469 found = f;
3470 #else
3471 if (wdesc == XtWindow (x->widget)
3472 || wdesc == XtWindow (x->column_widget)
3473 || wdesc == XtWindow (x->edit_widget))
3474 found = f;
3475 /* Match if the window is this frame's menubar. */
3476 else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
3477 found = f;
3478 #endif
3479 }
3480 else if (FRAME_X_WINDOW (f) == wdesc)
3481 /* A tooltip frame. */
3482 found = f;
3483 }
3484 }
3485
3486 return found;
3487 }
3488
3489 /* Likewise, but consider only the menu bar widget. */
3490
3491 static struct frame *
3492 x_menubar_window_to_frame (struct x_display_info *dpyinfo,
3493 const XEvent *event)
3494 {
3495 Window wdesc = event->xany.window;
3496 Lisp_Object tail, frame;
3497 struct frame *f;
3498 struct x_output *x;
3499
3500 if (wdesc == None)
3501 return NULL;
3502
3503 FOR_EACH_FRAME (tail, frame)
3504 {
3505 f = XFRAME (frame);
3506 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
3507 continue;
3508 x = f->output_data.x;
3509 #ifdef USE_GTK
3510 if (x->menubar_widget && xg_event_is_for_menubar (f, event))
3511 return f;
3512 #else
3513 /* Match if the window is this frame's menubar. */
3514 if (x->menubar_widget
3515 && lw_window_is_in_menubar (wdesc, x->menubar_widget))
3516 return f;
3517 #endif
3518 }
3519 return 0;
3520 }
3521
3522 /* Return the frame whose principal (outermost) window is WDESC.
3523 If WDESC is some other (smaller) window, we return 0. */
3524
3525 struct frame *
3526 x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
3527 {
3528 Lisp_Object tail, frame;
3529 struct frame *f;
3530 struct x_output *x;
3531
3532 if (wdesc == None)
3533 return NULL;
3534
3535 FOR_EACH_FRAME (tail, frame)
3536 {
3537 f = XFRAME (frame);
3538 if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
3539 continue;
3540 x = f->output_data.x;
3541
3542 if (x->widget)
3543 {
3544 /* This frame matches if the window is its topmost widget. */
3545 #ifdef USE_GTK
3546 GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
3547 if (gwdesc == x->widget)
3548 return f;
3549 #else
3550 if (wdesc == XtWindow (x->widget))
3551 return f;
3552 #endif
3553 }
3554 else if (FRAME_X_WINDOW (f) == wdesc)
3555 /* Tooltip frame. */
3556 return f;
3557 }
3558 return 0;
3559 }
3560
3561 #else /* !USE_X_TOOLKIT && !USE_GTK */
3562
3563 #define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
3564 #define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
3565
3566 #endif /* USE_X_TOOLKIT || USE_GTK */
3567
3568 /* The focus may have changed. Figure out if it is a real focus change,
3569 by checking both FocusIn/Out and Enter/LeaveNotify events.
3570
3571 Returns FOCUS_IN_EVENT event in *BUFP. */
3572
3573 static void
3574 x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
3575 const XEvent *event, struct input_event *bufp)
3576 {
3577 if (!frame)
3578 return;
3579
3580 switch (event->type)
3581 {
3582 case EnterNotify:
3583 case LeaveNotify:
3584 {
3585 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
3586 int focus_state
3587 = focus_frame ? focus_frame->output_data.x->focus_state : 0;
3588
3589 if (event->xcrossing.detail != NotifyInferior
3590 && event->xcrossing.focus
3591 && ! (focus_state & FOCUS_EXPLICIT))
3592 x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
3593 FOCUS_IMPLICIT,
3594 dpyinfo, frame, bufp);
3595 }
3596 break;
3597
3598 case FocusIn:
3599 case FocusOut:
3600 x_focus_changed (event->type,
3601 (event->xfocus.detail == NotifyPointer ?
3602 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3603 dpyinfo, frame, bufp);
3604 break;
3605
3606 case ClientMessage:
3607 if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
3608 {
3609 enum xembed_message msg = event->xclient.data.l[1];
3610 x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
3611 FOCUS_EXPLICIT, dpyinfo, frame, bufp);
3612 }
3613 break;
3614 }
3615 }
3616
3617
3618 #if !defined USE_X_TOOLKIT && !defined USE_GTK
3619 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3620
3621 void
3622 x_mouse_leave (struct x_display_info *dpyinfo)
3623 {
3624 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3625 }
3626 #endif
3627
3628 /* The focus has changed, or we have redirected a frame's focus to
3629 another frame (this happens when a frame uses a surrogate
3630 mini-buffer frame). Shift the highlight as appropriate.
3631
3632 The FRAME argument doesn't necessarily have anything to do with which
3633 frame is being highlighted or un-highlighted; we only use it to find
3634 the appropriate X display info. */
3635
3636 static void
3637 XTframe_rehighlight (struct frame *frame)
3638 {
3639 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
3640 }
3641
3642 static void
3643 x_frame_rehighlight (struct x_display_info *dpyinfo)
3644 {
3645 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3646
3647 if (dpyinfo->x_focus_frame)
3648 {
3649 dpyinfo->x_highlight_frame
3650 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3651 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3652 : dpyinfo->x_focus_frame);
3653 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3654 {
3655 fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
3656 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3657 }
3658 }
3659 else
3660 dpyinfo->x_highlight_frame = 0;
3661
3662 if (dpyinfo->x_highlight_frame != old_highlight)
3663 {
3664 if (old_highlight)
3665 frame_unhighlight (old_highlight);
3666 if (dpyinfo->x_highlight_frame)
3667 frame_highlight (dpyinfo->x_highlight_frame);
3668 }
3669 }
3670
3671
3672 \f
3673 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3674
3675 /* Initialize mode_switch_bit and modifier_meaning. */
3676 static void
3677 x_find_modifier_meanings (struct x_display_info *dpyinfo)
3678 {
3679 int min_code, max_code;
3680 KeySym *syms;
3681 int syms_per_code;
3682 XModifierKeymap *mods;
3683
3684 dpyinfo->meta_mod_mask = 0;
3685 dpyinfo->shift_lock_mask = 0;
3686 dpyinfo->alt_mod_mask = 0;
3687 dpyinfo->super_mod_mask = 0;
3688 dpyinfo->hyper_mod_mask = 0;
3689
3690 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3691
3692 syms = XGetKeyboardMapping (dpyinfo->display,
3693 min_code, max_code - min_code + 1,
3694 &syms_per_code);
3695 mods = XGetModifierMapping (dpyinfo->display);
3696
3697 /* Scan the modifier table to see which modifier bits the Meta and
3698 Alt keysyms are on. */
3699 {
3700 int row, col; /* The row and column in the modifier table. */
3701 bool found_alt_or_meta;
3702
3703 for (row = 3; row < 8; row++)
3704 {
3705 found_alt_or_meta = false;
3706 for (col = 0; col < mods->max_keypermod; col++)
3707 {
3708 KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
3709
3710 /* Zeroes are used for filler. Skip them. */
3711 if (code == 0)
3712 continue;
3713
3714 /* Are any of this keycode's keysyms a meta key? */
3715 {
3716 int code_col;
3717
3718 for (code_col = 0; code_col < syms_per_code; code_col++)
3719 {
3720 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3721
3722 switch (sym)
3723 {
3724 case XK_Meta_L:
3725 case XK_Meta_R:
3726 found_alt_or_meta = true;
3727 dpyinfo->meta_mod_mask |= (1 << row);
3728 break;
3729
3730 case XK_Alt_L:
3731 case XK_Alt_R:
3732 found_alt_or_meta = true;
3733 dpyinfo->alt_mod_mask |= (1 << row);
3734 break;
3735
3736 case XK_Hyper_L:
3737 case XK_Hyper_R:
3738 if (!found_alt_or_meta)
3739 dpyinfo->hyper_mod_mask |= (1 << row);
3740 code_col = syms_per_code;
3741 col = mods->max_keypermod;
3742 break;
3743
3744 case XK_Super_L:
3745 case XK_Super_R:
3746 if (!found_alt_or_meta)
3747 dpyinfo->super_mod_mask |= (1 << row);
3748 code_col = syms_per_code;
3749 col = mods->max_keypermod;
3750 break;
3751
3752 case XK_Shift_Lock:
3753 /* Ignore this if it's not on the lock modifier. */
3754 if (!found_alt_or_meta && ((1 << row) == LockMask))
3755 dpyinfo->shift_lock_mask = LockMask;
3756 code_col = syms_per_code;
3757 col = mods->max_keypermod;
3758 break;
3759 }
3760 }
3761 }
3762 }
3763 }
3764 }
3765
3766 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3767 if (! dpyinfo->meta_mod_mask)
3768 {
3769 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3770 dpyinfo->alt_mod_mask = 0;
3771 }
3772
3773 /* If some keys are both alt and meta,
3774 make them just meta, not alt. */
3775 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3776 {
3777 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3778 }
3779
3780 XFree (syms);
3781 XFreeModifiermap (mods);
3782 }
3783
3784 /* Convert between the modifier bits X uses and the modifier bits
3785 Emacs uses. */
3786
3787 int
3788 x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
3789 {
3790 int mod_meta = meta_modifier;
3791 int mod_alt = alt_modifier;
3792 int mod_hyper = hyper_modifier;
3793 int mod_super = super_modifier;
3794 Lisp_Object tem;
3795
3796 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3797 if (INTEGERP (tem)) mod_alt = XINT (tem) & INT_MAX;
3798 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3799 if (INTEGERP (tem)) mod_meta = XINT (tem) & INT_MAX;
3800 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3801 if (INTEGERP (tem)) mod_hyper = XINT (tem) & INT_MAX;
3802 tem = Fget (Vx_super_keysym, Qmodifier_value);
3803 if (INTEGERP (tem)) mod_super = XINT (tem) & INT_MAX;
3804
3805 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3806 | ((state & ControlMask) ? ctrl_modifier : 0)
3807 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
3808 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
3809 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
3810 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
3811 }
3812
3813 static int
3814 x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, EMACS_INT state)
3815 {
3816 EMACS_INT mod_meta = meta_modifier;
3817 EMACS_INT mod_alt = alt_modifier;
3818 EMACS_INT mod_hyper = hyper_modifier;
3819 EMACS_INT mod_super = super_modifier;
3820
3821 Lisp_Object tem;
3822
3823 tem = Fget (Vx_alt_keysym, Qmodifier_value);
3824 if (INTEGERP (tem)) mod_alt = XINT (tem);
3825 tem = Fget (Vx_meta_keysym, Qmodifier_value);
3826 if (INTEGERP (tem)) mod_meta = XINT (tem);
3827 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
3828 if (INTEGERP (tem)) mod_hyper = XINT (tem);
3829 tem = Fget (Vx_super_keysym, Qmodifier_value);
3830 if (INTEGERP (tem)) mod_super = XINT (tem);
3831
3832
3833 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
3834 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
3835 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
3836 | ((state & shift_modifier) ? ShiftMask : 0)
3837 | ((state & ctrl_modifier) ? ControlMask : 0)
3838 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
3839 }
3840
3841 /* Convert a keysym to its name. */
3842
3843 char *
3844 x_get_keysym_name (int keysym)
3845 {
3846 char *value;
3847
3848 block_input ();
3849 value = XKeysymToString (keysym);
3850 unblock_input ();
3851
3852 return value;
3853 }
3854
3855 /* Mouse clicks and mouse movement. Rah.
3856
3857 Formerly, we used PointerMotionHintMask (in standard_event_mask)
3858 so that we would have to call XQueryPointer after each MotionNotify
3859 event to ask for another such event. However, this made mouse tracking
3860 slow, and there was a bug that made it eventually stop.
3861
3862 Simply asking for MotionNotify all the time seems to work better.
3863
3864 In order to avoid asking for motion events and then throwing most
3865 of them away or busy-polling the server for mouse positions, we ask
3866 the server for pointer motion hints. This means that we get only
3867 one event per group of mouse movements. "Groups" are delimited by
3868 other kinds of events (focus changes and button clicks, for
3869 example), or by XQueryPointer calls; when one of these happens, we
3870 get another MotionNotify event the next time the mouse moves. This
3871 is at least as efficient as getting motion events when mouse
3872 tracking is on, and I suspect only negligibly worse when tracking
3873 is off. */
3874
3875 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3876
3877 If the event is a button press, then note that we have grabbed
3878 the mouse. */
3879
3880 static Lisp_Object
3881 construct_mouse_click (struct input_event *result,
3882 const XButtonEvent *event,
3883 struct frame *f)
3884 {
3885 /* Make the event type NO_EVENT; we'll change that when we decide
3886 otherwise. */
3887 result->kind = MOUSE_CLICK_EVENT;
3888 result->code = event->button - Button1;
3889 result->timestamp = event->time;
3890 result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
3891 event->state)
3892 | (event->type == ButtonRelease
3893 ? up_modifier
3894 : down_modifier));
3895
3896 XSETINT (result->x, event->x);
3897 XSETINT (result->y, event->y);
3898 XSETFRAME (result->frame_or_window, f);
3899 result->arg = Qnil;
3900 return Qnil;
3901 }
3902
3903 /* Function to report a mouse movement to the mainstream Emacs code.
3904 The input handler calls this.
3905
3906 We have received a mouse movement event, which is given in *event.
3907 If the mouse is over a different glyph than it was last time, tell
3908 the mainstream emacs code by setting mouse_moved. If not, ask for
3909 another motion event, so we can check again the next time it moves. */
3910
3911 static bool
3912 note_mouse_movement (struct frame *frame, const XMotionEvent *event)
3913 {
3914 XRectangle *r;
3915 struct x_display_info *dpyinfo;
3916
3917 if (!FRAME_X_OUTPUT (frame))
3918 return false;
3919
3920 dpyinfo = FRAME_DISPLAY_INFO (frame);
3921 dpyinfo->last_mouse_movement_time = event->time;
3922 dpyinfo->last_mouse_motion_frame = frame;
3923 dpyinfo->last_mouse_motion_x = event->x;
3924 dpyinfo->last_mouse_motion_y = event->y;
3925
3926 if (event->window != FRAME_X_WINDOW (frame))
3927 {
3928 frame->mouse_moved = true;
3929 dpyinfo->last_mouse_scroll_bar = NULL;
3930 note_mouse_highlight (frame, -1, -1);
3931 dpyinfo->last_mouse_glyph_frame = NULL;
3932 return true;
3933 }
3934
3935
3936 /* Has the mouse moved off the glyph it was on at the last sighting? */
3937 r = &dpyinfo->last_mouse_glyph;
3938 if (frame != dpyinfo->last_mouse_glyph_frame
3939 || event->x < r->x || event->x >= r->x + r->width
3940 || event->y < r->y || event->y >= r->y + r->height)
3941 {
3942 frame->mouse_moved = true;
3943 dpyinfo->last_mouse_scroll_bar = NULL;
3944 note_mouse_highlight (frame, event->x, event->y);
3945 /* Remember which glyph we're now on. */
3946 remember_mouse_glyph (frame, event->x, event->y, r);
3947 dpyinfo->last_mouse_glyph_frame = frame;
3948 return true;
3949 }
3950
3951 return false;
3952 }
3953
3954 /* Return the current position of the mouse.
3955 *FP should be a frame which indicates which display to ask about.
3956
3957 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3958 and *PART to the frame, window, and scroll bar part that the mouse
3959 is over. Set *X and *Y to the portion and whole of the mouse's
3960 position on the scroll bar.
3961
3962 If the mouse movement started elsewhere, set *FP to the frame the
3963 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3964 the mouse is over.
3965
3966 Set *TIMESTAMP to the server time-stamp for the time at which the mouse
3967 was at this position.
3968
3969 Don't store anything if we don't have a valid set of values to report.
3970
3971 This clears the mouse_moved flag, so we can wait for the next mouse
3972 movement. */
3973
3974 static void
3975 XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3976 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3977 Time *timestamp)
3978 {
3979 struct frame *f1;
3980 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
3981
3982 block_input ();
3983
3984 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
3985 {
3986 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
3987
3988 if (bar->horizontal)
3989 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3990 else
3991 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3992 }
3993 else
3994 {
3995 Window root;
3996 int root_x, root_y;
3997
3998 Window dummy_window;
3999 int dummy;
4000
4001 Lisp_Object frame, tail;
4002
4003 /* Clear the mouse-moved flag for every frame on this display. */
4004 FOR_EACH_FRAME (tail, frame)
4005 if (FRAME_X_P (XFRAME (frame))
4006 && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
4007 XFRAME (frame)->mouse_moved = false;
4008
4009 dpyinfo->last_mouse_scroll_bar = NULL;
4010
4011 /* Figure out which root window we're on. */
4012 XQueryPointer (FRAME_X_DISPLAY (*fp),
4013 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
4014
4015 /* The root window which contains the pointer. */
4016 &root,
4017
4018 /* Trash which we can't trust if the pointer is on
4019 a different screen. */
4020 &dummy_window,
4021
4022 /* The position on that root window. */
4023 &root_x, &root_y,
4024
4025 /* More trash we can't trust. */
4026 &dummy, &dummy,
4027
4028 /* Modifier keys and pointer buttons, about which
4029 we don't care. */
4030 (unsigned int *) &dummy);
4031
4032 /* Now we have a position on the root; find the innermost window
4033 containing the pointer. */
4034 {
4035 Window win, child;
4036 int win_x, win_y;
4037 int parent_x = 0, parent_y = 0;
4038
4039 win = root;
4040
4041 /* XTranslateCoordinates can get errors if the window
4042 structure is changing at the same time this function
4043 is running. So at least we must not crash from them. */
4044
4045 x_catch_errors (FRAME_X_DISPLAY (*fp));
4046
4047 if (x_mouse_grabbed (dpyinfo))
4048 {
4049 /* If mouse was grabbed on a frame, give coords for that frame
4050 even if the mouse is now outside it. */
4051 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
4052
4053 /* From-window. */
4054 root,
4055
4056 /* To-window. */
4057 FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
4058
4059 /* From-position, to-position. */
4060 root_x, root_y, &win_x, &win_y,
4061
4062 /* Child of win. */
4063 &child);
4064 f1 = dpyinfo->last_mouse_frame;
4065 }
4066 else
4067 {
4068 while (true)
4069 {
4070 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
4071
4072 /* From-window, to-window. */
4073 root, win,
4074
4075 /* From-position, to-position. */
4076 root_x, root_y, &win_x, &win_y,
4077
4078 /* Child of win. */
4079 &child);
4080
4081 if (child == None || child == win)
4082 break;
4083 #ifdef USE_GTK
4084 /* We don't wan't to know the innermost window. We
4085 want the edit window. For non-Gtk+ the innermost
4086 window is the edit window. For Gtk+ it might not
4087 be. It might be the tool bar for example. */
4088 if (x_window_to_frame (dpyinfo, win))
4089 break;
4090 #endif
4091 win = child;
4092 parent_x = win_x;
4093 parent_y = win_y;
4094 }
4095
4096 /* Now we know that:
4097 win is the innermost window containing the pointer
4098 (XTC says it has no child containing the pointer),
4099 win_x and win_y are the pointer's position in it
4100 (XTC did this the last time through), and
4101 parent_x and parent_y are the pointer's position in win's parent.
4102 (They are what win_x and win_y were when win was child.
4103 If win is the root window, it has no parent, and
4104 parent_{x,y} are invalid, but that's okay, because we'll
4105 never use them in that case.) */
4106
4107 #ifdef USE_GTK
4108 /* We don't wan't to know the innermost window. We
4109 want the edit window. */
4110 f1 = x_window_to_frame (dpyinfo, win);
4111 #else
4112 /* Is win one of our frames? */
4113 f1 = x_any_window_to_frame (dpyinfo, win);
4114 #endif
4115
4116 #ifdef USE_X_TOOLKIT
4117 /* If we end up with the menu bar window, say it's not
4118 on the frame. */
4119 if (f1 != NULL
4120 && f1->output_data.x->menubar_widget
4121 && win == XtWindow (f1->output_data.x->menubar_widget))
4122 f1 = NULL;
4123 #endif /* USE_X_TOOLKIT */
4124 }
4125
4126 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
4127 f1 = 0;
4128
4129 x_uncatch_errors ();
4130
4131 /* If not, is it one of our scroll bars? */
4132 if (! f1)
4133 {
4134 struct scroll_bar *bar;
4135
4136 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
4137
4138 if (bar)
4139 {
4140 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4141 win_x = parent_x;
4142 win_y = parent_y;
4143 }
4144 }
4145
4146 if (f1 == 0 && insist > 0)
4147 f1 = SELECTED_FRAME ();
4148
4149 if (f1)
4150 {
4151 /* Ok, we found a frame. Store all the values.
4152 last_mouse_glyph is a rectangle used to reduce the
4153 generation of mouse events. To not miss any motion
4154 events, we must divide the frame into rectangles of the
4155 size of the smallest character that could be displayed
4156 on it, i.e. into the same rectangles that matrices on
4157 the frame are divided into. */
4158
4159 /* FIXME: what if F1 is not an X frame? */
4160 dpyinfo = FRAME_DISPLAY_INFO (f1);
4161 remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
4162 dpyinfo->last_mouse_glyph_frame = f1;
4163
4164 *bar_window = Qnil;
4165 *part = scroll_bar_above_handle;
4166 *fp = f1;
4167 XSETINT (*x, win_x);
4168 XSETINT (*y, win_y);
4169 *timestamp = dpyinfo->last_mouse_movement_time;
4170 }
4171 }
4172 }
4173
4174 unblock_input ();
4175 }
4176
4177
4178 \f
4179 /***********************************************************************
4180 Scroll bars
4181 ***********************************************************************/
4182
4183 /* Scroll bar support. */
4184
4185 /* Given an X window ID and a DISPLAY, find the struct scroll_bar which
4186 manages it.
4187 This can be called in GC, so we have to make sure to strip off mark
4188 bits. */
4189
4190 static struct scroll_bar *
4191 x_window_to_scroll_bar (Display *display, Window window_id, int type)
4192 {
4193 Lisp_Object tail, frame;
4194
4195 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
4196 window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
4197 #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
4198
4199 FOR_EACH_FRAME (tail, frame)
4200 {
4201 Lisp_Object bar, condemned;
4202
4203 if (! FRAME_X_P (XFRAME (frame)))
4204 continue;
4205
4206 /* Scan this frame's scroll bar list for a scroll bar with the
4207 right window ID. */
4208 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
4209 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
4210 /* This trick allows us to search both the ordinary and
4211 condemned scroll bar lists with one loop. */
4212 ! NILP (bar) || (bar = condemned,
4213 condemned = Qnil,
4214 ! NILP (bar));
4215 bar = XSCROLL_BAR (bar)->next)
4216 if (XSCROLL_BAR (bar)->x_window == window_id
4217 && FRAME_X_DISPLAY (XFRAME (frame)) == display
4218 && (type = 2
4219 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
4220 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
4221 return XSCROLL_BAR (bar);
4222 }
4223
4224 return NULL;
4225 }
4226
4227
4228 #if defined USE_LUCID
4229
4230 /* Return the Lucid menu bar WINDOW is part of. Return null
4231 if WINDOW is not part of a menu bar. */
4232
4233 static Widget
4234 x_window_to_menu_bar (Window window)
4235 {
4236 Lisp_Object tail, frame;
4237
4238 FOR_EACH_FRAME (tail, frame)
4239 if (FRAME_X_P (XFRAME (frame)))
4240 {
4241 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
4242
4243 if (menu_bar && xlwmenu_window_p (menu_bar, window))
4244 return menu_bar;
4245 }
4246 return NULL;
4247 }
4248
4249 #endif /* USE_LUCID */
4250
4251 \f
4252 /************************************************************************
4253 Toolkit scroll bars
4254 ************************************************************************/
4255
4256 #ifdef USE_TOOLKIT_SCROLL_BARS
4257
4258 static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
4259 int, int, bool);
4260
4261 /* Lisp window being scrolled. Set when starting to interact with
4262 a toolkit scroll bar, reset to nil when ending the interaction. */
4263
4264 static Lisp_Object window_being_scrolled;
4265
4266 /* Whether this is an Xaw with arrow-scrollbars. This should imply
4267 that movements of 1/20 of the screen size are mapped to up/down. */
4268
4269 #ifndef USE_GTK
4270 /* Id of action hook installed for scroll bars. */
4271
4272 static XtActionHookId action_hook_id;
4273 static XtActionHookId horizontal_action_hook_id;
4274
4275 static Boolean xaw3d_arrow_scroll;
4276
4277 /* Whether the drag scrolling maintains the mouse at the top of the
4278 thumb. If not, resizing the thumb needs to be done more carefully
4279 to avoid jerkiness. */
4280
4281 static Boolean xaw3d_pick_top;
4282
4283 /* Action hook installed via XtAppAddActionHook when toolkit scroll
4284 bars are used.. The hook is responsible for detecting when
4285 the user ends an interaction with the scroll bar, and generates
4286 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
4287
4288 static void
4289 xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4290 XEvent *event, String *params, Cardinal *num_params)
4291 {
4292 bool scroll_bar_p;
4293 const char *end_action;
4294
4295 #ifdef USE_MOTIF
4296 scroll_bar_p = XmIsScrollBar (widget);
4297 end_action = "Release";
4298 #else /* !USE_MOTIF i.e. use Xaw */
4299 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4300 end_action = "EndScroll";
4301 #endif /* USE_MOTIF */
4302
4303 if (scroll_bar_p
4304 && strcmp (action_name, end_action) == 0
4305 && WINDOWP (window_being_scrolled))
4306 {
4307 struct window *w;
4308 struct scroll_bar *bar;
4309
4310 x_send_scroll_bar_event (window_being_scrolled,
4311 scroll_bar_end_scroll, 0, 0, false);
4312 w = XWINDOW (window_being_scrolled);
4313 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4314
4315 if (bar->dragging != -1)
4316 {
4317 bar->dragging = -1;
4318 /* The thumb size is incorrect while dragging: fix it. */
4319 set_vertical_scroll_bar (w);
4320 }
4321 window_being_scrolled = Qnil;
4322 #if defined (USE_LUCID)
4323 bar->last_seen_part = scroll_bar_nowhere;
4324 #endif
4325 /* Xt timeouts no longer needed. */
4326 toolkit_scroll_bar_interaction = false;
4327 }
4328 }
4329
4330
4331 static void
4332 xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
4333 XEvent *event, String *params, Cardinal *num_params)
4334 {
4335 bool scroll_bar_p;
4336 const char *end_action;
4337
4338 #ifdef USE_MOTIF
4339 scroll_bar_p = XmIsScrollBar (widget);
4340 end_action = "Release";
4341 #else /* !USE_MOTIF i.e. use Xaw */
4342 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4343 end_action = "EndScroll";
4344 #endif /* USE_MOTIF */
4345
4346 if (scroll_bar_p
4347 && strcmp (action_name, end_action) == 0
4348 && WINDOWP (window_being_scrolled))
4349 {
4350 struct window *w;
4351 struct scroll_bar *bar;
4352
4353 x_send_scroll_bar_event (window_being_scrolled,
4354 scroll_bar_end_scroll, 0, 0, true);
4355 w = XWINDOW (window_being_scrolled);
4356 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
4357
4358 if (bar->dragging != -1)
4359 {
4360 bar->dragging = -1;
4361 /* The thumb size is incorrect while dragging: fix it. */
4362 set_horizontal_scroll_bar (w);
4363 }
4364 window_being_scrolled = Qnil;
4365 #if defined (USE_LUCID)
4366 bar->last_seen_part = scroll_bar_nowhere;
4367 #endif
4368 /* Xt timeouts no longer needed. */
4369 toolkit_scroll_bar_interaction = false;
4370 }
4371 }
4372 #endif /* not USE_GTK */
4373
4374 /* Send a client message with message type Xatom_Scrollbar for a
4375 scroll action to the frame of WINDOW. PART is a value identifying
4376 the part of the scroll bar that was clicked on. PORTION is the
4377 amount to scroll of a whole of WHOLE. */
4378
4379 static void
4380 x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
4381 int portion, int whole, bool horizontal)
4382 {
4383 XEvent event;
4384 XClientMessageEvent *ev = &event.xclient;
4385 struct window *w = XWINDOW (window);
4386 struct frame *f = XFRAME (w->frame);
4387 intptr_t iw = (intptr_t) w;
4388 enum { BITS_PER_INTPTR = CHAR_BIT * sizeof iw };
4389 verify (BITS_PER_INTPTR <= 64);
4390 int sign_shift = BITS_PER_INTPTR - 32;
4391
4392 block_input ();
4393
4394 /* Construct a ClientMessage event to send to the frame. */
4395 ev->type = ClientMessage;
4396 ev->message_type = (horizontal
4397 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
4398 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
4399 ev->display = FRAME_X_DISPLAY (f);
4400 ev->window = FRAME_X_WINDOW (f);
4401 ev->format = 32;
4402
4403 /* A 32-bit X client on a 64-bit X server can pass a window pointer
4404 as-is. A 64-bit client on a 32-bit X server is in trouble
4405 because a pointer does not fit and would be truncated while
4406 passing through the server. So use two slots and hope that X12
4407 will resolve such issues someday. */
4408 ev->data.l[0] = iw >> 31 >> 1;
4409 ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
4410 ev->data.l[2] = part;
4411 ev->data.l[3] = portion;
4412 ev->data.l[4] = whole;
4413
4414 /* Make Xt timeouts work while the scroll bar is active. */
4415 #ifdef USE_X_TOOLKIT
4416 toolkit_scroll_bar_interaction = true;
4417 x_activate_timeout_atimer ();
4418 #endif
4419
4420 /* Setting the event mask to zero means that the message will
4421 be sent to the client that created the window, and if that
4422 window no longer exists, no event will be sent. */
4423 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
4424 unblock_input ();
4425 }
4426
4427
4428 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
4429 in *IEVENT. */
4430
4431 static void
4432 x_scroll_bar_to_input_event (const XEvent *event,
4433 struct input_event *ievent)
4434 {
4435 const XClientMessageEvent *ev = &event->xclient;
4436 Lisp_Object window;
4437 struct window *w;
4438
4439 /* See the comment in the function above. */
4440 intptr_t iw0 = ev->data.l[0];
4441 intptr_t iw1 = ev->data.l[1];
4442 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
4443 w = (struct window *) iw;
4444
4445 XSETWINDOW (window, w);
4446
4447 ievent->kind = SCROLL_BAR_CLICK_EVENT;
4448 ievent->frame_or_window = window;
4449 ievent->arg = Qnil;
4450 #ifdef USE_GTK
4451 ievent->timestamp = CurrentTime;
4452 #else
4453 ievent->timestamp =
4454 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
4455 #endif
4456 ievent->code = 0;
4457 ievent->part = ev->data.l[2];
4458 ievent->x = make_number (ev->data.l[3]);
4459 ievent->y = make_number (ev->data.l[4]);
4460 ievent->modifiers = 0;
4461 }
4462
4463 /* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
4464 input event in *IEVENT. */
4465
4466 static void
4467 x_horizontal_scroll_bar_to_input_event (const XEvent *event,
4468 struct input_event *ievent)
4469 {
4470 const XClientMessageEvent *ev = &event->xclient;
4471 Lisp_Object window;
4472 struct window *w;
4473
4474 /* See the comment in the function above. */
4475 intptr_t iw0 = ev->data.l[0];
4476 intptr_t iw1 = ev->data.l[1];
4477 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
4478 w = (struct window *) iw;
4479
4480 XSETWINDOW (window, w);
4481
4482 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
4483 ievent->frame_or_window = window;
4484 ievent->arg = Qnil;
4485 #ifdef USE_GTK
4486 ievent->timestamp = CurrentTime;
4487 #else
4488 ievent->timestamp =
4489 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
4490 #endif
4491 ievent->code = 0;
4492 ievent->part = ev->data.l[2];
4493 ievent->x = make_number (ev->data.l[3]);
4494 ievent->y = make_number (ev->data.l[4]);
4495 ievent->modifiers = 0;
4496 }
4497
4498
4499 #ifdef USE_MOTIF
4500
4501 /* Minimum and maximum values used for Motif scroll bars. */
4502
4503 #define XM_SB_MAX 10000000
4504
4505 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4506 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4507 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
4508
4509 static void
4510 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4511 {
4512 struct scroll_bar *bar = client_data;
4513 XmScrollBarCallbackStruct *cs = call_data;
4514 enum scroll_bar_part part = scroll_bar_nowhere;
4515 bool horizontal = bar->horizontal;
4516 int whole = 0, portion = 0;
4517
4518 switch (cs->reason)
4519 {
4520 case XmCR_DECREMENT:
4521 bar->dragging = -1;
4522 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
4523 break;
4524
4525 case XmCR_INCREMENT:
4526 bar->dragging = -1;
4527 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
4528 break;
4529
4530 case XmCR_PAGE_DECREMENT:
4531 bar->dragging = -1;
4532 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
4533 break;
4534
4535 case XmCR_PAGE_INCREMENT:
4536 bar->dragging = -1;
4537 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
4538 break;
4539
4540 case XmCR_TO_TOP:
4541 bar->dragging = -1;
4542 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
4543 break;
4544
4545 case XmCR_TO_BOTTOM:
4546 bar->dragging = -1;
4547 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
4548 break;
4549
4550 case XmCR_DRAG:
4551 {
4552 int slider_size;
4553
4554 block_input ();
4555 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4556 unblock_input ();
4557
4558 if (horizontal)
4559 {
4560 portion = bar->whole * ((float)cs->value / XM_SB_MAX);
4561 whole = bar->whole * ((float)(XM_SB_MAX - slider_size) / XM_SB_MAX);
4562 portion = min (portion, whole);
4563 part = scroll_bar_horizontal_handle;
4564 }
4565 else
4566 {
4567 whole = XM_SB_MAX - slider_size;
4568 portion = min (cs->value, whole);
4569 part = scroll_bar_handle;
4570 }
4571
4572 bar->dragging = cs->value;
4573 }
4574 break;
4575
4576 case XmCR_VALUE_CHANGED:
4577 break;
4578 };
4579
4580 if (part != scroll_bar_nowhere)
4581 {
4582 window_being_scrolled = bar->window;
4583 x_send_scroll_bar_event (bar->window, part, portion, whole,
4584 bar->horizontal);
4585 }
4586 }
4587
4588 #elif defined USE_GTK
4589
4590 /* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
4591 bar widget. DATA is a pointer to the scroll_bar structure. */
4592
4593 static gboolean
4594 xg_scroll_callback (GtkRange *range,
4595 GtkScrollType scroll,
4596 gdouble value,
4597 gpointer user_data)
4598 {
4599 int whole = 0, portion = 0;
4600 struct scroll_bar *bar = user_data;
4601 enum scroll_bar_part part = scroll_bar_nowhere;
4602 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
4603 struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
4604
4605 if (xg_ignore_gtk_scrollbar) return FALSE;
4606
4607 switch (scroll)
4608 {
4609 case GTK_SCROLL_JUMP:
4610 /* Buttons 1 2 or 3 must be grabbed. */
4611 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
4612 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
4613 {
4614 if (bar->horizontal)
4615 {
4616 part = scroll_bar_horizontal_handle;
4617 whole = (int)(gtk_adjustment_get_upper (adj) -
4618 gtk_adjustment_get_page_size (adj));
4619 portion = min ((int)value, whole);
4620 bar->dragging = portion;
4621 }
4622 else
4623 {
4624 part = scroll_bar_handle;
4625 whole = gtk_adjustment_get_upper (adj) -
4626 gtk_adjustment_get_page_size (adj);
4627 portion = min ((int)value, whole);
4628 bar->dragging = portion;
4629 }
4630 }
4631 break;
4632 case GTK_SCROLL_STEP_BACKWARD:
4633 part = (bar->horizontal
4634 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
4635 bar->dragging = -1;
4636 break;
4637 case GTK_SCROLL_STEP_FORWARD:
4638 part = (bar->horizontal
4639 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
4640 bar->dragging = -1;
4641 break;
4642 case GTK_SCROLL_PAGE_BACKWARD:
4643 part = (bar->horizontal
4644 ? scroll_bar_before_handle : scroll_bar_above_handle);
4645 bar->dragging = -1;
4646 break;
4647 case GTK_SCROLL_PAGE_FORWARD:
4648 part = (bar->horizontal
4649 ? scroll_bar_after_handle : scroll_bar_below_handle);
4650 bar->dragging = -1;
4651 break;
4652 }
4653
4654 if (part != scroll_bar_nowhere)
4655 {
4656 window_being_scrolled = bar->window;
4657 x_send_scroll_bar_event (bar->window, part, portion, whole,
4658 bar->horizontal);
4659 }
4660
4661 return FALSE;
4662 }
4663
4664 /* Callback for button release. Sets dragging to -1 when dragging is done. */
4665
4666 static gboolean
4667 xg_end_scroll_callback (GtkWidget *widget,
4668 GdkEventButton *event,
4669 gpointer user_data)
4670 {
4671 struct scroll_bar *bar = user_data;
4672 bar->dragging = -1;
4673 if (WINDOWP (window_being_scrolled))
4674 {
4675 x_send_scroll_bar_event (window_being_scrolled,
4676 scroll_bar_end_scroll, 0, 0, bar->horizontal);
4677 window_being_scrolled = Qnil;
4678 }
4679
4680 return FALSE;
4681 }
4682
4683
4684 #else /* not USE_GTK and not USE_MOTIF */
4685
4686 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
4687 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
4688 scroll bar struct. CALL_DATA is a pointer to a float saying where
4689 the thumb is. */
4690
4691 static void
4692 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4693 {
4694 struct scroll_bar *bar = client_data;
4695 float *top_addr = call_data;
4696 float top = *top_addr;
4697 float shown;
4698 int whole, portion, height, width;
4699 enum scroll_bar_part part;
4700 bool horizontal = bar->horizontal;
4701
4702
4703 if (horizontal)
4704 {
4705 /* Get the size of the thumb, a value between 0 and 1. */
4706 block_input ();
4707 XtVaGetValues (widget, XtNshown, &shown, XtNwidth, &width, NULL);
4708 unblock_input ();
4709
4710 if (shown < 1)
4711 {
4712 whole = bar->whole - (shown * bar->whole);
4713 portion = min (top * bar->whole, whole);
4714 }
4715 else
4716 {
4717 whole = bar->whole;
4718 portion = 0;
4719 }
4720
4721 part = scroll_bar_horizontal_handle;
4722 }
4723 else
4724 {
4725 /* Get the size of the thumb, a value between 0 and 1. */
4726 block_input ();
4727 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4728 unblock_input ();
4729
4730 whole = 10000000;
4731 portion = shown < 1 ? top * whole : 0;
4732
4733 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height))
4734 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
4735 the bottom, so we force the scrolling whenever we see that we're
4736 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
4737 we try to ensure that we always stay two pixels away from the
4738 bottom). */
4739 part = scroll_bar_down_arrow;
4740 else
4741 part = scroll_bar_handle;
4742 }
4743
4744 window_being_scrolled = bar->window;
4745 bar->dragging = portion;
4746 bar->last_seen_part = part;
4747 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
4748 }
4749
4750
4751 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
4752 i.e. line or page up or down. WIDGET is the Xaw scroll bar
4753 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
4754 the scroll bar. CALL_DATA is an integer specifying the action that
4755