]> code.delx.au - gnu-emacs/blob - src/xterm.c
* emacs.c (Finvocation_name): New function.
[gnu-emacs] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* Serious problems:
21
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
25
26 */
27
28 #define NEW_SELECTIONS
29
30 #include "config.h"
31
32 #ifdef HAVE_X_WINDOWS
33
34 #include "lisp.h"
35
36 /* On 4.3 these lose if they come after xterm.h. */
37 #include <stdio.h>
38 #include <signal.h>
39
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
42 #include "xterm.h"
43 #include <X11/cursorfont.h>
44
45 #ifndef USG
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
48 #ifndef makedev
49 #include <sys/types.h>
50 #endif /* makedev */
51 #endif /* USG */
52
53 #ifdef BSD
54 #include <sys/ioctl.h>
55 #include <strings.h>
56 #else /* ! defined (BSD) */
57 #include <sys/termio.h>
58 #include <string.h>
59 #endif /* ! defined (BSD) */
60
61 /* Allow m- file to inhibit use of FIONREAD. */
62 #ifdef BROKEN_FIONREAD
63 #undef FIONREAD
64 #endif /* ! defined (BROKEN_FIONREAD) */
65
66 /* We are unable to use interrupts if FIONREAD is not available,
67 so flush SIGIO so we won't try. */
68 #ifndef FIONREAD
69 #ifdef SIGIO
70 #undef SIGIO
71 #endif /* ! defined (SIGIO) */
72 #endif /* FIONREAD */
73
74 #include "systime.h"
75
76 #include <fcntl.h>
77 #include <ctype.h>
78 #include <errno.h>
79 #include <setjmp.h>
80 #include <sys/stat.h>
81 #include <sys/param.h>
82
83 #include "dispextern.h"
84 #include "termhooks.h"
85 #include "termopts.h"
86 #include "termchar.h"
87 #if 0
88 #include "sink.h"
89 #include "sinkmask.h"
90 #endif /* ! 0 */
91 #include "gnu.h"
92 #include "frame.h"
93 #include "disptab.h"
94 #include "buffer.h"
95 #include "window.h"
96
97 #ifdef HAVE_X11
98 #define XMapWindow XMapRaised /* Raise them when mapping. */
99 #else /* ! defined (HAVE_X11) */
100 #include <X/Xkeyboard.h>
101 /*#include <X/Xproto.h> */
102 #endif /* ! defined (HAVE_X11) */
103
104 /* For sending Meta-characters. Do we need this? */
105 #define METABIT 0200
106
107 #define min(a,b) ((a)<(b) ? (a) : (b))
108 #define max(a,b) ((a)>(b) ? (a) : (b))
109
110 /* Nonzero means we must reprint all windows
111 because 1) we received an ExposeWindow event
112 or 2) we received too many ExposeRegion events to record.
113
114 This is never needed under X11. */
115 static int expose_all_windows;
116
117 /* Nonzero means we must reprint all icon windows. */
118
119 static int expose_all_icons;
120
121 #ifndef HAVE_X11
122 /* ExposeRegion events, when received, are copied into this queue
123 for later processing. */
124
125 static struct event_queue x_expose_queue;
126
127 /* ButtonPressed and ButtonReleased events, when received,
128 are copied into this queue for later processing. */
129
130 struct event_queue x_mouse_queue;
131 #endif /* HAVE_X11 */
132
133 /* Nonzero after BLOCK_INPUT; prevents input events from being
134 processed until later. */
135
136 int x_input_blocked;
137
138 #if defined (SIGIO) && defined (FIONREAD)
139 int BLOCK_INPUT_mask;
140 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
141
142 /* Nonzero if input events came in while x_input_blocked was nonzero.
143 UNBLOCK_INPUT checks for this. */
144
145 int x_pending_input;
146
147 /* The id of a bitmap used for icon windows.
148 One such map is shared by all Emacs icon windows.
149 This is zero if we have not yet had a need to create the bitmap. */
150
151 static Bitmap icon_bitmap;
152
153 /* Font used for text icons. */
154
155 static FONT_TYPE *icon_font_info;
156
157 /* Stuff for dealing with the main icon title. */
158
159 extern Lisp_Object Vcommand_line_args;
160 char *hostname, *x_id_name;
161
162 /* This is the X connection that we are using. */
163
164 Display *x_current_display;
165
166 /* The cursor to use for vertical scroll bars on x_current_display. */
167 static Cursor x_vertical_scroll_bar_cursor;
168
169 /* Frame being updated by update_frame. */
170 /* This is set by XTupdate_begin and looked at by all the
171 XT functions. It is zero while not inside an update.
172 In that case, the XT functions assume that `selected_frame'
173 is the frame to apply to. */
174
175 static struct frame *updating_frame;
176
177 /* The frame (if any) which has the X window that has keyboard focus.
178 Zero if none. This is examined by Ffocus_frame in frame.c. Note
179 that a mere EnterNotify event can set this; if you need to know the
180 last frame specified in a FocusIn or FocusOut event, use
181 x_focus_event_frame. */
182 struct frame *x_focus_frame;
183
184 /* The last frame mentioned in a FocusIn or FocusOut event. This is
185 separate from x_focus_frame, because whether or not LeaveNotify
186 events cause us to lose focus depends on whether or not we have
187 received a FocusIn event for it. */
188 struct frame *x_focus_event_frame;
189
190 /* The frame which currently has the visual highlight, and should get
191 keyboard input (other sorts of input have the frame encoded in the
192 event). It points to the X focus frame's selected window's
193 frame. It differs from x_focus_frame when we're using a global
194 minibuffer. */
195 static struct frame *x_highlight_frame;
196
197 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
198 mouse is moved to inside of frame when frame is de-iconified. */
199
200 static int warp_mouse_on_deiconify;
201
202 /* During an update, maximum vpos for ins/del line operations to affect. */
203
204 static int flexlines;
205
206 /* During an update, nonzero if chars output now should be highlighted. */
207
208 static int highlight;
209
210 /* Nominal cursor position -- where to draw output.
211 During an update, these are different from the cursor-box position. */
212
213 static int curs_x;
214 static int curs_y;
215
216 #ifdef HAVE_X11
217 /* `t' if a mouse button is depressed. */
218
219 extern Lisp_Object Vmouse_depressed;
220
221 /* Tells if a window manager is present or not. */
222
223 extern Lisp_Object Vx_no_window_manager;
224
225 /* Timestamp that we requested selection data was made. */
226 extern Time requestor_time;
227
228 /* ID of the window requesting selection data. */
229 extern Window requestor_window;
230
231 /* Nonzero enables some debugging for the X interface code. */
232 extern int _Xdebug;
233
234 #else /* ! defined (HAVE_X11) */
235
236 /* Bit patterns for the mouse cursor. */
237
238 short MouseCursor[] = {
239 0x0000, 0x0008, 0x0018, 0x0038,
240 0x0078, 0x00f8, 0x01f8, 0x03f8,
241 0x07f8, 0x00f8, 0x00d8, 0x0188,
242 0x0180, 0x0300, 0x0300, 0x0000};
243
244 short MouseMask[] = {
245 0x000c, 0x001c, 0x003c, 0x007c,
246 0x00fc, 0x01fc, 0x03fc, 0x07fc,
247 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
248 0x03cc, 0x0780, 0x0780, 0x0300};
249
250 static short grey_bits[] = {
251 0x0005, 0x000a, 0x0005, 0x000a};
252
253 static Pixmap GreyPixmap = 0;
254 #endif /* ! defined (HAVE_X11) */
255
256 /* From time to time we get info on an Emacs window, here. */
257
258 static WINDOWINFO_TYPE windowinfo;
259
260 extern int errno;
261
262 /* See keyboard.c. */
263 extern int extra_keyboard_modifiers;
264
265 extern Display *XOpenDisplay ();
266 extern Window XCreateWindow ();
267
268 extern Cursor XCreateCursor ();
269 extern FONT_TYPE *XOpenFont ();
270
271 static void flashback ();
272
273 #ifndef HAVE_X11
274 static void dumpqueue ();
275 #endif /* HAVE_X11 */
276
277 void dumpborder ();
278 static int XTcursor_to ();
279 static int XTclear_end_of_line ();
280
281 \f
282 /* Starting and ending updates.
283
284 These hooks are called by update_frame at the beginning and end
285 of a frame update. We record in `updating_frame' the identity
286 of the frame being updated, so that the XT... functions do not
287 need to take a frame as argument. Most of the XT... functions
288 should never be called except during an update, the only exceptions
289 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
290
291 extern int mouse_track_top, mouse_track_left, mouse_track_width;
292
293 static
294 XTupdate_begin (f)
295 struct frame *f;
296 {
297 int mask;
298
299 if (f == 0)
300 abort ();
301
302 updating_frame = f;
303 flexlines = f->height;
304 highlight = 0;
305
306 BLOCK_INPUT;
307 #ifndef HAVE_X11
308 dumpqueue ();
309 #endif /* HAVE_X11 */
310 UNBLOCK_INPUT;
311 }
312
313 #ifndef HAVE_X11
314 static void x_do_pending_expose ();
315 #endif
316
317 static
318 XTupdate_end (f)
319 struct frame *f;
320 {
321 int mask;
322
323 if (updating_frame == 0
324 || updating_frame != f)
325 abort ();
326
327 BLOCK_INPUT;
328 #ifndef HAVE_X11
329 dumpqueue ();
330 x_do_pending_expose ();
331 #endif /* HAVE_X11 */
332
333 x_display_cursor (f, 1);
334
335 updating_frame = 0;
336 XFlushQueue ();
337 UNBLOCK_INPUT;
338 }
339 \f
340 /* External interface to control of standout mode.
341 Call this when about to modify line at position VPOS
342 and not change whether it is highlighted. */
343
344 XTreassert_line_highlight (new, vpos)
345 int new, vpos;
346 {
347 highlight = new;
348 }
349
350 /* Call this when about to modify line at position VPOS
351 and change whether it is highlighted. */
352
353 static
354 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
355 int new_highlight, vpos, first_unused_hpos;
356 {
357 highlight = new_highlight;
358 XTcursor_to (vpos, 0);
359 XTclear_end_of_line (updating_frame->width);
360 }
361
362 /* This is used when starting Emacs and when restarting after suspend.
363 When starting Emacs, no X window is mapped. And nothing must be done
364 to Emacs's own window if it is suspended (though that rarely happens). */
365
366 static
367 XTset_terminal_modes ()
368 {
369 }
370
371 /* This is called when exiting or suspending Emacs.
372 Exiting will make the X-windows go away, and suspending
373 requires no action. */
374
375 static
376 XTreset_terminal_modes ()
377 {
378 /* XTclear_frame (); */
379 }
380 \f
381 /* Set the nominal cursor position of the frame.
382 This is where display update commands will take effect.
383 This does not affect the place where the cursor-box is displayed. */
384
385 static int
386 XTcursor_to (row, col)
387 register int row, col;
388 {
389 int mask;
390 int orow = row;
391
392 curs_x = col;
393 curs_y = row;
394
395 if (updating_frame == 0)
396 {
397 BLOCK_INPUT;
398 x_display_cursor (selected_frame, 1);
399 XFlushQueue ();
400 UNBLOCK_INPUT;
401 }
402 }
403 \f
404 /* Display a sequence of N glyphs found at GP.
405 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
406 HL is 1 if this text is highlighted, 2 if the cursor is on it.
407
408 FONT is the default font to use (for glyphs whose font-code is 0). */
409
410 static void
411 dumpglyphs (f, left, top, gp, n, hl, font)
412 struct frame *f;
413 int left, top;
414 register GLYPH *gp; /* Points to first GLYPH. */
415 register int n; /* Number of glyphs to display. */
416 int hl;
417 FONT_TYPE *font;
418 {
419 register int len;
420 Window window = FRAME_X_WINDOW (f);
421 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
422 : (hl ? f->display.x->reverse_gc
423 : f->display.x->normal_gc));
424
425 if (sizeof (GLYPH) == sizeof (XChar2b))
426 XDrawImageString16 (x_current_display, window, drawing_gc,
427 left, top + FONT_BASE (font), (XChar2b *) gp, n);
428 else if (sizeof (GLYPH) == sizeof (unsigned char))
429 XDrawImageString (x_current_display, window, drawing_gc,
430 left, top + FONT_BASE (font), (char *) gp, n);
431 else
432 /* What size of glyph ARE you using? And does X have a function to
433 draw them? */
434 abort ();
435 }
436
437 #if 0
438 static void
439 dumpglyphs (f, left, top, gp, n, hl, font)
440 struct frame *f;
441 int left, top;
442 register GLYPH *gp; /* Points to first GLYPH. */
443 register int n; /* Number of glyphs to display. */
444 int hl;
445 FONT_TYPE *font;
446 {
447 char buf[f->width]; /* Holds characters to be displayed. */
448 register char *cp; /* Steps through buf[]. */
449 register int tlen = GLYPH_TABLE_LENGTH;
450 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
451 Window window = FRAME_X_WINDOW (f);
452 int cursor_pixel = f->display.x->cursor_pixel;
453 int fg_pixel = f->display.x->foreground_pixel;
454 int bg_pixel = f->display.x->background_pixel;
455 int intborder = f->display.x->internal_border_width;
456
457 while (n)
458 {
459 /* Get the face-code of the next GLYPH. */
460 int cf, len;
461 int g = *gp;
462
463 while (GLYPH_ALIAS_P (tbase, tlen, g))
464 g = GLYPH_ALIAS (tbase, g);
465
466 cf = g >> 8;
467
468 /* Find the run of consecutive glyphs with the same face-code.
469 Extract their character codes into BUF. */
470 cp = buf;
471 while (n > 0)
472 {
473 g = *gp;
474 while (GLYPH_ALIAS_P (tbase, tlen, g))
475 g = GLYPH_ALIAS (tbase, g);
476 if ((g >> 8) != cf)
477 break;
478
479 *cp++ = 0377 & g;
480 --n;
481 ++gp;
482 }
483
484 /* LEN gets the length of the run. */
485 len = cp - buf;
486
487 /* Now output this run of chars, with the font and pixel values
488 determined by the face code CF. */
489 if (cf == 0)
490 {
491 #ifdef HAVE_X11
492 GC GC_cursor = f->display.x->cursor_gc;
493 GC GC_reverse = f->display.x->reverse_gc;
494 GC GC_normal = f->display.x->normal_gc;
495
496 XDrawImageString (x_current_display, window,
497 (hl == 2
498 ? GC_cursor
499 : (hl ? GC_reverse : GC_normal)),
500 left, top + FONT_BASE (font), buf, len);
501 #else /* ! defined (HAVE_X11) */
502 XText (window, left, top,
503 buf,
504 len,
505 font->id,
506 (hl == 2
507 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
508 : hl ? bg_pixel : fg_pixel),
509 (hl == 2 ? cursor_pixel
510 : hl ? fg_pixel : bg_pixel));
511 #endif /* ! defined (HAVE_X11) */
512 }
513 else
514 {
515 #ifdef HAVE_X11
516 if (FACE_IS_FONT (cf))
517 XDrawImageString (x_current_display, FRAME_X_WINDOW (f),
518 FACE_GC (cf),
519 left, top + FONT_BASE (FACE_FONT (cf)),
520 buf, len);
521 else if (FACE_IS_IMAGE (cf))
522 XCopyPlane (x_current_display, FACE_IMAGE (cf),
523 FRAME_X_WINDOW (f),
524 f->display.x->normal_gc,
525 0, 0,
526 FACE_IMAGE_WIDTH (cf),
527 FACE_IMAGE_HEIGHT (cf), left, top);
528 else
529 abort ();
530 #else /* ! defined (HAVE_X11) */
531 register struct face *fp = x_face_table[cf];
532
533 XText (window, left, top,
534 buf,
535 len,
536 fp->font->id,
537 (hl == 2
538 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
539 : hl ? fp->bg : fp->fg),
540 (hl == 2 ? cursor_pixel
541 : hl ? fp->fg : fp->bg));
542 #endif /* ! defined (HAVE_X11) */
543 }
544 left += len * FONT_WIDTH (font);
545 }
546 }
547 #endif /* ! 0 */
548 \f
549 /* Output some text at the nominal frame cursor position.
550 Advance the cursor over the text.
551 Output LEN glyphs at START.
552
553 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
554 controls the pixel values used for foreground and background. */
555
556 static
557 XTwrite_glyphs (start, len)
558 register GLYPH *start;
559 int len;
560 {
561 register int temp_length;
562 int mask;
563 struct frame *f;
564
565 BLOCK_INPUT;
566
567 f = updating_frame;
568 if (f == 0)
569 {
570 f = selected_frame;
571 /* If not within an update,
572 output at the frame's visible cursor. */
573 curs_x = f->cursor_x;
574 curs_y = f->cursor_y;
575 }
576
577 dumpglyphs (f,
578 CHAR_TO_PIXEL_COL (f, curs_x),
579 CHAR_TO_PIXEL_ROW (f, curs_y),
580 start, len, highlight, f->display.x->font);
581
582 /* If we drew on top of the cursor, note that it is turned off. */
583 if (curs_y == f->phys_cursor_y
584 && curs_x <= f->phys_cursor_x
585 && curs_x + len > f->phys_cursor_x)
586 f->phys_cursor_x = -1;
587
588 if (updating_frame == 0)
589 {
590 f->cursor_x += len;
591 x_display_cursor (f, 1);
592 f->cursor_x -= len;
593 }
594 else
595 curs_x += len;
596
597 UNBLOCK_INPUT;
598 }
599 \f
600 /* Clear to the end of the line.
601 Erase the current text line from the nominal cursor position (inclusive)
602 to column FIRST_UNUSED (exclusive). The idea is that everything
603 from FIRST_UNUSED onward is already erased. */
604
605 static int
606 XTclear_end_of_line (first_unused)
607 register int first_unused;
608 {
609 struct frame *f = updating_frame;
610 int mask;
611
612 if (f == 0)
613 abort ();
614
615 if (curs_y < 0 || curs_y >= f->height)
616 return;
617 if (first_unused <= 0)
618 return;
619
620 if (first_unused >= f->width)
621 first_unused = f->width;
622
623 BLOCK_INPUT;
624
625 /* Notice if the cursor will be cleared by this operation. */
626 if (curs_y == f->phys_cursor_y
627 && curs_x <= f->phys_cursor_x
628 && f->phys_cursor_x < first_unused)
629 f->phys_cursor_x = -1;
630
631 #ifdef HAVE_X11
632 XClearArea (x_current_display, FRAME_X_WINDOW (f),
633 CHAR_TO_PIXEL_COL (f, curs_x),
634 CHAR_TO_PIXEL_ROW (f, curs_y),
635 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
636 FONT_HEIGHT (f->display.x->font), False);
637
638 #else /* ! defined (HAVE_X11) */
639 XPixSet (FRAME_X_WINDOW (f),
640 CHAR_TO_PIXEL_COL (f, curs_x),
641 CHAR_TO_PIXEL_ROW (f, curs_y),
642 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
643 FONT_HEIGHT (f->display.x->font),
644 f->display.x->background_pixel);
645 #endif /* ! defined (HAVE_X11) */
646
647 UNBLOCK_INPUT;
648 }
649
650 static
651 XTclear_frame ()
652 {
653 int mask;
654 struct frame *f = updating_frame;
655
656 if (f == 0)
657 f = selected_frame;
658
659 f->phys_cursor_x = -1; /* Cursor not visible. */
660 curs_x = 0; /* Nominal cursor position is top left. */
661 curs_y = 0;
662
663 BLOCK_INPUT;
664
665 XClear (FRAME_X_WINDOW (f));
666
667 /* We have to clear the scroll bars, too. If we have changed
668 colors or something like that, then they should be notified. */
669 x_scroll_bar_clear (f);
670
671 #ifndef HAVE_X11
672 dumpborder (f, 0);
673 #endif /* HAVE_X11 */
674
675 XFlushQueue ();
676 UNBLOCK_INPUT;
677 }
678 \f
679 /* Invert the middle quarter of the frame for .15 sec. */
680
681 /* We use the select system call to do the waiting, so we have to make sure
682 it's avaliable. If it isn't, we just won't do visual bells. */
683 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
684
685 /* Subtract the `struct timeval' values X and Y,
686 storing the result in RESULT.
687 Return 1 if the difference is negative, otherwise 0. */
688
689 static int
690 timeval_subtract (result, x, y)
691 struct timeval *result, x, y;
692 {
693 /* Perform the carry for the later subtraction by updating y.
694 This is safer because on some systems
695 the tv_sec member is unsigned. */
696 if (x.tv_usec < y.tv_usec)
697 {
698 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
699 y.tv_usec -= 1000000 * nsec;
700 y.tv_sec += nsec;
701 }
702 if (x.tv_usec - y.tv_usec > 1000000)
703 {
704 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
705 y.tv_usec += 1000000 * nsec;
706 y.tv_sec -= nsec;
707 }
708
709 /* Compute the time remaining to wait. tv_usec is certainly positive. */
710 result->tv_sec = x.tv_sec - y.tv_sec;
711 result->tv_usec = x.tv_usec - y.tv_usec;
712
713 /* Return indication of whether the result should be considered negative. */
714 return x.tv_sec < y.tv_sec;
715 }
716
717 XTflash (f)
718 struct frame *f;
719 {
720 BLOCK_INPUT;
721
722 {
723 GC gc;
724
725 /* Create a GC that will use the GXxor function to flip foreground pixels
726 into background pixels. */
727 {
728 XGCValues values;
729
730 values.function = GXxor;
731 values.foreground = (f->display.x->foreground_pixel
732 ^ f->display.x->background_pixel);
733
734 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
735 GCFunction | GCForeground, &values);
736 }
737
738 {
739 int width = PIXEL_WIDTH (f);
740 int height = PIXEL_HEIGHT (f);
741
742 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
743 width/4, height/4, width/2, height/2);
744 XFlush (x_current_display);
745
746 {
747 struct timeval wakeup, now;
748
749 gettimeofday (&wakeup, (struct timezone *) 0);
750
751 /* Compute time to wait until, propagating carry from usecs. */
752 wakeup.tv_usec += 150000;
753 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
754 wakeup.tv_usec %= 1000000;
755
756 /* Keep waiting until past the time wakeup. */
757 while (1)
758 {
759 struct timeval timeout;
760
761 gettimeofday (&timeout, (struct timezone *)0);
762
763 /* In effect, timeout = wakeup - timeout.
764 Break if result would be negative. */
765 if (timeval_subtract (&timeout, wakeup, timeout))
766 break;
767
768 /* Try to wait that long--but we might wake up sooner. */
769 select (0, 0, 0, 0, &timeout);
770 }
771 }
772
773 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
774 width/4, height/4, width/2, height/2);
775 XFreeGC (x_current_display, gc);
776 XFlush (x_current_display);
777 }
778 }
779
780 UNBLOCK_INPUT;
781 }
782
783 #endif
784
785
786 /* Make audible bell. */
787
788 #ifdef HAVE_X11
789 #define XRINGBELL XBell(x_current_display, 0)
790 #else /* ! defined (HAVE_X11) */
791 #define XRINGBELL XFeep(0);
792 #endif /* ! defined (HAVE_X11) */
793
794 XTring_bell ()
795 {
796 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
797 if (visible_bell)
798 XTflash (selected_frame);
799 else
800 #endif
801 {
802 BLOCK_INPUT;
803 XRINGBELL;
804 XFlushQueue ();
805 UNBLOCK_INPUT;
806 }
807 }
808 \f
809 /* Insert and delete character.
810 These are not supposed to be used because we are supposed to turn
811 off the feature of using them. */
812
813 static
814 XTinsert_glyphs (start, len)
815 register char *start;
816 register int len;
817 {
818 abort ();
819 }
820
821 static
822 XTdelete_glyphs (n)
823 register int n;
824 {
825 abort ();
826 }
827 \f
828 /* Specify how many text lines, from the top of the window,
829 should be affected by insert-lines and delete-lines operations.
830 This, and those operations, are used only within an update
831 that is bounded by calls to XTupdate_begin and XTupdate_end. */
832
833 static
834 XTset_terminal_window (n)
835 register int n;
836 {
837 if (updating_frame == 0)
838 abort ();
839
840 if ((n <= 0) || (n > updating_frame->height))
841 flexlines = updating_frame->height;
842 else
843 flexlines = n;
844 }
845 \f
846 /* Perform an insert-lines operation.
847 Insert N lines at a vertical position curs_y. */
848
849 static void
850 stufflines (n)
851 register int n;
852 {
853 register int topregion, bottomregion;
854 register int length, newtop, mask;
855 register struct frame *f = updating_frame;
856 int intborder = f->display.x->internal_border_width;
857
858 if (curs_y >= flexlines)
859 return;
860
861 topregion = curs_y;
862 bottomregion = flexlines - (n + 1);
863 newtop = topregion + n;
864 length = (bottomregion - topregion) + 1;
865
866 #ifndef HAVE_X11
867 dumpqueue ();
868 #endif /* HAVE_X11 */
869
870 if ((length > 0) && (newtop <= flexlines))
871 {
872 #ifdef HAVE_X11
873 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
874 FRAME_X_WINDOW (f), f->display.x->normal_gc,
875 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
876 f->width * FONT_WIDTH (f->display.x->font),
877 length * FONT_HEIGHT (f->display.x->font), intborder,
878 CHAR_TO_PIXEL_ROW (f, newtop));
879 #else /* ! defined (HAVE_X11) */
880 XMoveArea (FRAME_X_WINDOW (f),
881 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
882 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
883 f->width * FONT_WIDTH (f->display.x->font),
884 length * FONT_HEIGHT (f->display.x->font));
885 /* Now we must process any ExposeRegion events that occur
886 if the area being copied from is obscured.
887 We can't let it wait because further i/d operations
888 may want to copy this area to another area. */
889 x_read_exposes ();
890 #endif /* ! defined (HAVE_X11) */
891 }
892
893 newtop = min (newtop, (flexlines - 1));
894 length = newtop - topregion;
895 if (length > 0)
896 {
897 #ifdef HAVE_X11
898 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
899 CHAR_TO_PIXEL_ROW (f, topregion),
900 f->width * FONT_WIDTH (f->display.x->font),
901 n * FONT_HEIGHT (f->display.x->font), False);
902 #else /* ! defined (HAVE_X11) */
903 XPixSet (FRAME_X_WINDOW (f),
904 intborder,
905 CHAR_TO_PIXEL_ROW (f, topregion),
906 f->width * FONT_WIDTH (f->display.x->font),
907 n * FONT_HEIGHT (f->display.x->font),
908 f->display.x->background_pixel);
909 #endif /* ! defined (HAVE_X11) */
910 }
911 }
912
913 /* Perform a delete-lines operation, deleting N lines
914 at a vertical position curs_y. */
915
916 static void
917 scraplines (n)
918 register int n;
919 {
920 int mask;
921 register struct frame *f = updating_frame;
922 int intborder = f->display.x->internal_border_width;
923
924 if (curs_y >= flexlines)
925 return;
926
927 #ifndef HAVE_X11
928 dumpqueue ();
929 #endif /* HAVE_X11 */
930
931 if ((curs_y + n) >= flexlines)
932 {
933 if (flexlines >= (curs_y + 1))
934 {
935 #ifdef HAVE_X11
936 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
937 CHAR_TO_PIXEL_ROW (f, curs_y),
938 f->width * FONT_WIDTH (f->display.x->font),
939 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
940 #else /* ! defined (HAVE_X11) */
941 XPixSet (FRAME_X_WINDOW (f),
942 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
943 f->width * FONT_WIDTH (f->display.x->font),
944 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
945 f->display.x->background_pixel);
946 #endif /* ! defined (HAVE_X11) */
947 }
948 }
949 else
950 {
951 #ifdef HAVE_X11
952 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
953 FRAME_X_WINDOW (f), f->display.x->normal_gc,
954 intborder,
955 CHAR_TO_PIXEL_ROW (f, curs_y + n),
956 f->width * FONT_WIDTH (f->display.x->font),
957 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
958 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
959 XClearArea (x_current_display, FRAME_X_WINDOW (f),
960 intborder,
961 CHAR_TO_PIXEL_ROW (f, flexlines - n),
962 f->width * FONT_WIDTH (f->display.x->font),
963 n * FONT_HEIGHT (f->display.x->font), False);
964 #else /* ! defined (HAVE_X11) */
965 XMoveArea (FRAME_X_WINDOW (f),
966 intborder,
967 CHAR_TO_PIXEL_ROW (f, curs_y + n),
968 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
969 f->width * FONT_WIDTH (f->display.x->font),
970 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
971 /* Now we must process any ExposeRegion events that occur
972 if the area being copied from is obscured.
973 We can't let it wait because further i/d operations
974 may want to copy this area to another area. */
975 x_read_exposes ();
976 XPixSet (FRAME_X_WINDOW (f), intborder,
977 CHAR_TO_PIXEL_ROW (f, flexlines - n),
978 f->width * FONT_WIDTH (f->display.x->font),
979 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
980 #endif /* ! defined (HAVE_X11) */
981 }
982 }
983
984 /* Perform an insert-lines or delete-lines operation,
985 inserting N lines or deleting -N lines at vertical position VPOS. */
986
987 XTins_del_lines (vpos, n)
988 int vpos, n;
989 {
990 if (updating_frame == 0)
991 abort ();
992
993 /* Hide the cursor. */
994 x_display_cursor (updating_frame, 0);
995
996 XTcursor_to (vpos, 0);
997
998 BLOCK_INPUT;
999 if (n >= 0)
1000 stufflines (n);
1001 else
1002 scraplines (-n);
1003 XFlushQueue ();
1004 UNBLOCK_INPUT;
1005 }
1006 \f
1007 /* Support routines for exposure events. */
1008 static void clear_cursor ();
1009
1010 /* Output into a rectangle of an X-window (for frame F)
1011 the characters in f->phys_lines that overlap that rectangle.
1012 TOP and LEFT are the position of the upper left corner of the rectangle.
1013 ROWS and COLS are the size of the rectangle. */
1014
1015 static void
1016 dumprectangle (f, left, top, cols, rows)
1017 struct frame *f;
1018 register int left, top, cols, rows;
1019 {
1020 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1021 int cursor_cleared = 0;
1022 int bottom, right;
1023 register int y;
1024
1025 if (FRAME_GARBAGED_P (f))
1026 return;
1027
1028 /* Express rectangle as four edges, instead of position-and-size. */
1029 bottom = top + rows;
1030 right = left + cols;
1031
1032 #ifndef HAVE_X11 /* Window manger does this for X11. */
1033 {
1034 int intborder = f->display.x->internal_border_width;
1035
1036 /* If the rectangle includes any of the internal border area,
1037 redisplay the border emphasis. */
1038 if (top < intborder || left < intborder
1039 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1040 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1041 dumpborder (f, 0);
1042 }
1043 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1044
1045 /* Convert rectangle edges in pixels to edges in chars.
1046 Round down for left and top, up for right and bottom. */
1047 top = PIXEL_TO_CHAR_ROW (f, top);
1048 left = PIXEL_TO_CHAR_COL (f, left);
1049 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1050 right += (FONT_WIDTH (f->display.x->font) - 1);
1051 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1052 right = PIXEL_TO_CHAR_COL (f, right);
1053
1054 /* Clip the rectangle to what can be visible. */
1055 if (left < 0)
1056 left = 0;
1057 if (top < 0)
1058 top = 0;
1059 if (right > f->width)
1060 right = f->width;
1061 if (bottom > f->height)
1062 bottom = f->height;
1063
1064 /* Get size in chars of the rectangle. */
1065 cols = right - left;
1066 rows = bottom - top;
1067
1068 /* If rectangle has zero area, return. */
1069 if (rows <= 0) return;
1070 if (cols <= 0) return;
1071
1072 /* Turn off the cursor if it is in the rectangle.
1073 We will turn it back on afterward. */
1074 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1075 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1076 {
1077 clear_cursor (f);
1078 cursor_cleared = 1;
1079 }
1080
1081 /* Display the text in the rectangle, one text line at a time. */
1082
1083 for (y = top; y < bottom; y++)
1084 {
1085 GLYPH *line = &active_frame->glyphs[y][left];
1086
1087 if (! active_frame->enable[y] || left > active_frame->used[y])
1088 continue;
1089
1090 dumpglyphs (f,
1091 CHAR_TO_PIXEL_COL (f, left),
1092 CHAR_TO_PIXEL_ROW (f, y),
1093 line, min (cols, active_frame->used[y] - left),
1094 active_frame->highlight[y], f->display.x->font);
1095 }
1096
1097 /* Turn the cursor on if we turned it off. */
1098
1099 if (cursor_cleared)
1100 x_display_cursor (f, 1);
1101 }
1102
1103 #ifndef HAVE_X11
1104 /* Process all queued ExposeRegion events. */
1105
1106 static void
1107 dumpqueue ()
1108 {
1109 register int i;
1110 XExposeRegionEvent r;
1111
1112 while (dequeue_event (&r, &x_expose_queue))
1113 {
1114 struct frame *f = x_window_to_frame (r.window);
1115 if (f->display.x->icon_desc == r.window)
1116 refreshicon (f);
1117 else
1118 dumprectangle (f, r.x, r.y, r.width, r.height);
1119 }
1120 XFlushQueue ();
1121 }
1122 #endif /* HAVE_X11 */
1123 \f
1124 /* Process all expose events that are pending, for X10.
1125 Redraws the cursor if necessary on any frame that
1126 is not in the process of being updated with update_frame. */
1127
1128 #ifndef HAVE_X11
1129 static void
1130 x_do_pending_expose ()
1131 {
1132 int mask;
1133 struct frame *f;
1134 Lisp_Object tail, frame;
1135
1136 if (expose_all_windows)
1137 {
1138 expose_all_windows = 0;
1139 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1140 {
1141 register int temp_width, temp_height;
1142 int intborder;
1143
1144 frame = XCONS (tail)->car;
1145 if (XGCTYPE (frame) != Lisp_Frame)
1146 continue;
1147 f = XFRAME (frame);
1148 if (! FRAME_X_P (f))
1149 continue;
1150 if (!f->async_visible)
1151 continue;
1152 if (!f->display.x->needs_exposure)
1153 continue;
1154
1155 intborder = f->display.x->internal_border_width;
1156
1157 clear_cursor (f);
1158 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1159 temp_width = ((windowinfo.width - 2 * intborder
1160 - f->display.x->v_scroll_bar_width)
1161 / FONT_WIDTH (f->display.x->font));
1162 temp_height = ((windowinfo.height- 2 * intborder
1163 - f->display.x->h_scroll_bar_height)
1164 / FONT_HEIGHT (f->display.x->font));
1165 if (temp_width != f->width || temp_height != f->height)
1166 {
1167 change_frame_size (f, max (1, temp_height),
1168 max (1, temp_width), 0, 1);
1169 x_resize_scroll_bars (f);
1170 }
1171 f->display.x->left_pos = windowinfo.x;
1172 f->display.x->top_pos = windowinfo.y;
1173 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1174 #if 0
1175 dumpborder (f, 0);
1176 #endif /* ! 0 */
1177 f->display.x->needs_exposure = 0;
1178 if (updating_frame != f)
1179 x_display_cursor (f, 1);
1180 XFlushQueue ();
1181 }
1182 }
1183 else
1184 /* Handle any individual-rectangle expose events queued
1185 for various windows. */
1186 #ifdef HAVE_X11
1187 ;
1188 #else /* ! defined (HAVE_X11) */
1189 dumpqueue ();
1190 #endif /* ! defined (HAVE_X11) */
1191 }
1192 #endif
1193
1194 #ifdef HAVE_X11
1195 static void
1196 frame_highlight (frame)
1197 struct frame *frame;
1198 {
1199 if (! EQ (Vx_no_window_manager, Qnil))
1200 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1201 frame->display.x->border_pixel);
1202 x_display_cursor (frame, 1);
1203 }
1204
1205 static void
1206 frame_unhighlight (frame)
1207 struct frame *frame;
1208 {
1209 if (! EQ (Vx_no_window_manager, Qnil))
1210 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1211 frame->display.x->border_tile);
1212 x_display_cursor (frame, 1);
1213 }
1214 #else /* ! defined (HAVE_X11) */
1215 /* Dump the border-emphasis of frame F.
1216 If F is selected, this is a lining of the same color as the border,
1217 just within the border, occupying a portion of the internal border.
1218 If F is not selected, it is background in the same place.
1219 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1220
1221 ALWAYS = 1 is used when a frame becomes selected or deselected.
1222 In that case, we also turn the cursor off and on again
1223 so it will appear in the proper shape (solid if selected; else hollow.) */
1224
1225 static void
1226 dumpborder (f, always)
1227 struct frame *f;
1228 int always;
1229 {
1230 int thickness = f->display.x->internal_border_width / 2;
1231 int width = PIXEL_WIDTH (f);
1232 int height = PIXEL_HEIGHT (f);
1233 int pixel;
1234
1235 if (f != selected_frame)
1236 {
1237 if (!always)
1238 return;
1239
1240 pixel = f->display.x->background_pixel;
1241 }
1242 else
1243 {
1244 pixel = f->display.x->border_pixel;
1245 }
1246
1247 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1248 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1249 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1250 thickness, pixel);
1251 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1252 height, pixel);
1253
1254 if (always)
1255 x_display_cursor (f, 1);
1256 }
1257 #endif /* ! defined (HAVE_X11) */
1258
1259 static void XTframe_rehighlight ();
1260
1261 /* The focus has changed. Update the frames as necessary to reflect
1262 the new situation. Note that we can't change the selected frame
1263 here, because the lisp code we are interrupting might become confused.
1264 Each event gets marked with the frame in which it occured, so the
1265 lisp code can tell when the switch took place by examining the events. */
1266
1267 static void
1268 x_new_focus_frame (frame)
1269 struct frame *frame;
1270 {
1271 struct frame *old_focus = x_focus_frame;
1272 int events_enqueued = 0;
1273
1274 if (frame != x_focus_frame)
1275 {
1276 /* Set this before calling other routines, so that they see
1277 the correct value of x_focus_frame. */
1278 x_focus_frame = frame;
1279
1280 if (old_focus && old_focus->auto_lower)
1281 x_lower_frame (old_focus);
1282
1283 #if 0
1284 selected_frame = frame;
1285 XSET (XWINDOW (selected_frame->selected_window)->frame,
1286 Lisp_Frame, selected_frame);
1287 Fselect_window (selected_frame->selected_window);
1288 choose_minibuf_frame ();
1289 #endif /* ! 0 */
1290
1291 if (x_focus_frame && x_focus_frame->auto_raise)
1292 x_raise_frame (x_focus_frame);
1293 }
1294
1295 XTframe_rehighlight ();
1296 }
1297
1298
1299 /* The focus has changed, or we have redirected a frame's focus to
1300 another frame (this happens when a frame uses a surrogate
1301 minibuffer frame). Shift the highlight as appropriate. */
1302 static void
1303 XTframe_rehighlight ()
1304 {
1305 struct frame *old_highlight = x_highlight_frame;
1306
1307 if (x_focus_frame)
1308 {
1309 x_highlight_frame =
1310 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1311 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1312 : x_focus_frame);
1313 if (! FRAME_LIVE_P (x_highlight_frame))
1314 {
1315 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1316 x_highlight_frame = x_focus_frame;
1317 }
1318 }
1319 else
1320 x_highlight_frame = 0;
1321
1322 if (x_highlight_frame != old_highlight)
1323 {
1324 if (old_highlight)
1325 frame_unhighlight (old_highlight);
1326 if (x_highlight_frame)
1327 frame_highlight (x_highlight_frame);
1328 }
1329 }
1330 \f
1331 /* Mouse clicks and mouse movement. Rah. */
1332 #ifdef HAVE_X11
1333
1334 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1335 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1336 that the glyph at X, Y occupies, if BOUNDS != 0. */
1337 static void
1338 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1339 FRAME_PTR f;
1340 register unsigned int pix_x, pix_y;
1341 register int *x, *y;
1342 XRectangle *bounds;
1343 {
1344 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1345 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1346
1347 if (bounds)
1348 {
1349 bounds->width = FONT_WIDTH (f->display.x->font);
1350 bounds->height = FONT_HEIGHT (f->display.x->font);
1351 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1352 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1353 }
1354
1355 if (pix_x < 0) pix_x = 0;
1356 else if (pix_x > f->width) pix_x = f->width;
1357
1358 if (pix_y < 0) pix_y = 0;
1359 else if (pix_y > f->height) pix_y = f->height;
1360
1361 *x = pix_x;
1362 *y = pix_y;
1363 }
1364
1365 /* Any buttons grabbed. */
1366 unsigned int x_mouse_grabbed;
1367
1368 /* Which modifier keys are on which modifier bits?
1369
1370 With each keystroke, X returns eight bits indicating which modifier
1371 keys were held down when the key was pressed. The interpretation
1372 of the top five modifier bits depends on what keys are attached
1373 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1374 is the meta bit.
1375
1376 x_meta_mod_mask is a mask containing the bits used for the meta key.
1377 It may have more than one bit set, if more than one modifier bit
1378 has meta keys on it. Basically, if EVENT is a KeyPress event,
1379 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1380
1381 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1382 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1383 only be affected by the lock modifier bit if XK_Shift_Lock is in
1384 use; XK_Caps_Lock should only affect alphabetic keys. With this
1385 arrangement, the lock modifier should shift the character if
1386 (EVENT.state & x_shift_lock_mask) != 0. */
1387 static int x_meta_mod_mask, x_shift_lock_mask;
1388
1389 /* These are like x_meta_mod_mask, but for different modifiers. */
1390 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1391
1392 /* Initialize mode_switch_bit and modifier_meaning. */
1393 static void
1394 x_find_modifier_meanings ()
1395 {
1396 int min_code, max_code;
1397 KeySym *syms;
1398 int syms_per_code;
1399 XModifierKeymap *mods;
1400
1401 x_meta_mod_mask = 0;
1402 x_shift_lock_mask = 0;
1403 x_alt_mod_mask = 0;
1404 x_super_mod_mask = 0;
1405 x_hyper_mod_mask = 0;
1406
1407 #ifdef HAVE_X11R4
1408 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1409 #else
1410 min_code = x_current_display->min_keycode;
1411 max_code = x_current_display->max_keycode;
1412 #endif
1413
1414 syms = XGetKeyboardMapping (x_current_display,
1415 min_code, max_code - min_code + 1,
1416 &syms_per_code);
1417 mods = XGetModifierMapping (x_current_display);
1418
1419 /* Scan the modifier table to see which modifier bits the Meta and
1420 Alt keysyms are on. */
1421 {
1422 int row, col; /* The row and column in the modifier table. */
1423
1424 for (row = 3; row < 8; row++)
1425 for (col = 0; col < mods->max_keypermod; col++)
1426 {
1427 KeyCode code =
1428 mods->modifiermap[(row * mods->max_keypermod) + col];
1429
1430 /* Are any of this keycode's keysyms a meta key? */
1431 {
1432 int code_col;
1433
1434 for (code_col = 0; code_col < syms_per_code; code_col++)
1435 {
1436 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1437
1438 switch (sym)
1439 {
1440 case XK_Meta_L:
1441 case XK_Meta_R:
1442 x_meta_mod_mask |= (1 << row);
1443 break;
1444
1445 case XK_Alt_L:
1446 case XK_Alt_R:
1447 x_alt_mod_mask |= (1 << row);
1448 break;
1449
1450 case XK_Hyper_L:
1451 case XK_Hyper_R:
1452 x_hyper_mod_mask |= (1 << row);
1453 break;
1454
1455 case XK_Super_L:
1456 case XK_Super_R:
1457 x_super_mod_mask |= (1 << row);
1458 break;
1459
1460 case XK_Shift_Lock:
1461 /* Ignore this if it's not on the lock modifier. */
1462 if ((1 << row) == LockMask)
1463 x_shift_lock_mask = LockMask;
1464 break;
1465 }
1466 }
1467 }
1468 }
1469 }
1470
1471 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1472 if (! x_meta_mod_mask)
1473 {
1474 x_meta_mod_mask = x_alt_mod_mask;
1475 x_alt_mod_mask = 0;
1476 }
1477
1478 XFree ((char *) syms);
1479 XFreeModifiermap (mods);
1480 }
1481
1482
1483 /* Convert a set of X modifier bits to the proper form for a
1484 struct input_event modifiers value. */
1485
1486 static unsigned int
1487 x_convert_modifiers (state)
1488 unsigned int state;
1489 {
1490 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1491 | ((state & ControlMask) ? ctrl_modifier : 0)
1492 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1493 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1494 | ((state & x_super_mod_mask) ? super_modifier : 0)
1495 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1496 }
1497
1498 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1499
1500 If the event is a button press, then note that we have grabbed
1501 the mouse. */
1502
1503 static Lisp_Object
1504 construct_mouse_click (result, event, f)
1505 struct input_event *result;
1506 XButtonEvent *event;
1507 struct frame *f;
1508 {
1509 /* Make the event type no_event; we'll change that when we decide
1510 otherwise. */
1511 result->kind = mouse_click;
1512 XSET (result->code, Lisp_Int, event->button - Button1);
1513 result->timestamp = event->time;
1514 result->modifiers = (x_convert_modifiers (event->state)
1515 | (event->type == ButtonRelease
1516 ? up_modifier
1517 : down_modifier));
1518
1519 /* Notice if the mouse is still grabbed. */
1520 if (event->type == ButtonPress)
1521 {
1522 if (! x_mouse_grabbed)
1523 Vmouse_depressed = Qt;
1524 x_mouse_grabbed |= (1 << event->button);
1525 }
1526 else if (event->type == ButtonRelease)
1527 {
1528 x_mouse_grabbed &= ~(1 << event->button);
1529 if (!x_mouse_grabbed)
1530 Vmouse_depressed = Qnil;
1531 }
1532
1533 {
1534 int row, column;
1535
1536 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1537 XFASTINT (result->x) = column;
1538 XFASTINT (result->y) = row;
1539 XSET (result->frame_or_window, Lisp_Frame, f);
1540 }
1541 }
1542
1543
1544 /* Mouse movement. Rah.
1545
1546 In order to avoid asking for motion events and then throwing most
1547 of them away or busy-polling the server for mouse positions, we ask
1548 the server for pointer motion hints. This means that we get only
1549 one event per group of mouse movements. "Groups" are delimited by
1550 other kinds of events (focus changes and button clicks, for
1551 example), or by XQueryPointer calls; when one of these happens, we
1552 get another MotionNotify event the next time the mouse moves. This
1553 is at least as efficient as getting motion events when mouse
1554 tracking is on, and I suspect only negligibly worse when tracking
1555 is off.
1556
1557 The silly O'Reilly & Associates Nutshell guides barely document
1558 pointer motion hints at all (I think you have to infer how they
1559 work from an example), and the description of XQueryPointer doesn't
1560 mention that calling it causes you to get another motion hint from
1561 the server, which is very important. */
1562
1563 /* Where the mouse was last time we reported a mouse event. */
1564 static FRAME_PTR last_mouse_frame;
1565 static XRectangle last_mouse_glyph;
1566
1567 /* The scroll bar in which the last X motion event occurred.
1568
1569 If the last X motion event occured in a scroll bar, we set this
1570 so XTmouse_position can know whether to report a scroll bar motion or
1571 an ordinary motion.
1572
1573 If the last X motion event didn't occur in a scroll bar, we set this
1574 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1575 static Lisp_Object last_mouse_scroll_bar;
1576
1577 /* This is a hack. We would really prefer that XTmouse_position would
1578 return the time associated with the position it returns, but there
1579 doesn't seem to be any way to wrest the timestamp from the server
1580 along with the position query. So, we just keep track of the time
1581 of the last movement we received, and return that in hopes that
1582 it's somewhat accurate. */
1583 static Time last_mouse_movement_time;
1584
1585 /* Function to report a mouse movement to the mainstream Emacs code.
1586 The input handler calls this.
1587
1588 We have received a mouse movement event, which is given in *event.
1589 If the mouse is over a different glyph than it was last time, tell
1590 the mainstream emacs code by setting mouse_moved. If not, ask for
1591 another motion event, so we can check again the next time it moves. */
1592 static void
1593 note_mouse_movement (frame, event)
1594 FRAME_PTR frame;
1595 XMotionEvent *event;
1596
1597 {
1598 last_mouse_movement_time = event->time;
1599
1600 /* Has the mouse moved off the glyph it was on at the last sighting? */
1601 if (event->x < last_mouse_glyph.x
1602 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1603 || event->y < last_mouse_glyph.y
1604 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1605 {
1606 mouse_moved = 1;
1607 last_mouse_scroll_bar = Qnil;
1608 }
1609 else
1610 {
1611 /* It's on the same glyph. Call XQueryPointer so we'll get an
1612 event the next time the mouse moves and we can see if it's
1613 *still* on the same glyph. */
1614 int dummy;
1615
1616 XQueryPointer (event->display, event->window,
1617 (Window *) &dummy, (Window *) &dummy,
1618 &dummy, &dummy, &dummy, &dummy,
1619 (unsigned int *) &dummy);
1620 }
1621 }
1622
1623 static struct scroll_bar *x_window_to_scroll_bar ();
1624 static void x_scroll_bar_report_motion ();
1625
1626 /* Return the current position of the mouse.
1627
1628 If the mouse movement started in a scroll bar, set *f, *bar_window,
1629 and *part to the frame, window, and scroll bar part that the mouse
1630 is over. Set *x and *y to the portion and whole of the mouse's
1631 position on the scroll bar.
1632
1633 If the mouse movement started elsewhere, set *f to the frame the
1634 mouse is on, *bar_window to nil, and *x and *y to the character cell
1635 the mouse is over.
1636
1637 Set *time to the server timestamp for the time at which the mouse
1638 was at this position.
1639
1640 This clears the mouse_moved flag, so we can wait for the next mouse
1641 movement. This also calls XQueryPointer, which will cause the
1642 server to give us another MotionNotify when the mouse moves
1643 again. */
1644
1645 static void
1646 XTmouse_position (f, bar_window, part, x, y, time)
1647 FRAME_PTR *f;
1648 Lisp_Object *bar_window;
1649 enum scroll_bar_part *part;
1650 Lisp_Object *x, *y;
1651 unsigned long *time;
1652 {
1653 BLOCK_INPUT;
1654
1655 if (! NILP (last_mouse_scroll_bar))
1656 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1657 else
1658 {
1659 Window root;
1660 int root_x, root_y;
1661
1662 Window dummy_window;
1663 int dummy;
1664
1665 mouse_moved = 0;
1666 last_mouse_scroll_bar = Qnil;
1667
1668 /* Figure out which root window we're on. */
1669 XQueryPointer (x_current_display,
1670 DefaultRootWindow (x_current_display),
1671
1672 /* The root window which contains the pointer. */
1673 &root,
1674
1675 /* Trash which we can't trust if the pointer is on
1676 a different screen. */
1677 &dummy_window,
1678
1679 /* The position on that root window. */
1680 &root_x, &root_y,
1681
1682 /* More trash we can't trust. */
1683 &dummy, &dummy,
1684
1685 /* Modifier keys and pointer buttons, about which
1686 we don't care. */
1687 (unsigned int *) &dummy);
1688
1689 /* Now we have a position on the root; find the innermost window
1690 containing the pointer. */
1691 {
1692 Window win, child;
1693 int win_x, win_y;
1694 int parent_x, parent_y;
1695
1696 win = root;
1697 for (;;)
1698 {
1699 XTranslateCoordinates (x_current_display,
1700
1701 /* From-window, to-window. */
1702 root, win,
1703
1704 /* From-position, to-position. */
1705 root_x, root_y, &win_x, &win_y,
1706
1707 /* Child of win. */
1708 &child);
1709
1710 if (child == None)
1711 break;
1712
1713 win = child;
1714 parent_x = win_x;
1715 parent_y = win_y;
1716 }
1717
1718 /* Now we know that:
1719 win is the innermost window containing the pointer
1720 (XTC says it has no child containing the pointer),
1721 win_x and win_y are the pointer's position in it
1722 (XTC did this the last time through), and
1723 parent_x and parent_y are the pointer's position in win's parent.
1724 (They are what win_x and win_y were when win was child.
1725 If win is the root window, it has no parent, and
1726 parent_{x,y} are invalid, but that's okay, because we'll
1727 never use them in that case.) */
1728
1729 /* Is win one of our frames? */
1730 *f = x_window_to_frame (win);
1731
1732 /* If not, is it one of our scroll bars? */
1733 if (! *f)
1734 {
1735 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1736
1737 if (bar)
1738 {
1739 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1740 win_x = parent_x;
1741 win_y = parent_y;
1742 }
1743 }
1744
1745 if (*f)
1746 {
1747 pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y,
1748 &last_mouse_glyph);
1749
1750 *bar_window = Qnil;
1751 *part = 0;
1752 XSET (*x, Lisp_Int, win_x);
1753 XSET (*y, Lisp_Int, win_y);
1754 *time = last_mouse_movement_time;
1755 }
1756 }
1757 }
1758
1759 UNBLOCK_INPUT;
1760 }
1761
1762 #else /* ! defined (HAVE_X11) */
1763 #define XEvent XKeyPressedEvent
1764 #endif /* ! defined (HAVE_X11) */
1765 \f
1766 /* Scroll bar support. */
1767
1768 /* Given an X window ID, find the struct scroll_bar which manages it.
1769 This can be called in GC, so we have to make sure to strip off mark
1770 bits. */
1771 static struct scroll_bar *
1772 x_window_to_scroll_bar (window_id)
1773 Window window_id;
1774 {
1775 Lisp_Object tail, frame;
1776
1777 for (tail = Vframe_list;
1778 XGCTYPE (tail) == Lisp_Cons;
1779 tail = XCONS (tail)->cdr)
1780 {
1781 Lisp_Object frame = XCONS (tail)->car;
1782 Lisp_Object bar, condemned;
1783
1784 /* All elements of Vframe_list should be frames. */
1785 if (XGCTYPE (frame) != Lisp_Frame)
1786 abort ();
1787
1788 /* Scan this frame's scroll bar list for a scroll bar with the
1789 right window ID. */
1790 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1791 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1792 /* This trick allows us to search both the ordinary and
1793 condemned scroll bar lists with one loop. */
1794 ! GC_NILP (bar) || (bar = condemned,
1795 condemned = Qnil,
1796 ! GC_NILP (bar));
1797 bar = XSCROLL_BAR(bar)->next)
1798 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1799 return XSCROLL_BAR (bar);
1800 }
1801
1802 return 0;
1803 }
1804
1805 /* Open a new X window to serve as a scroll bar, and return the
1806 scroll bar vector for it. */
1807 static struct scroll_bar *
1808 x_scroll_bar_create (window, top, left, width, height)
1809 struct window *window;
1810 int top, left, width, height;
1811 {
1812 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1813 struct scroll_bar *bar =
1814 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1815
1816 BLOCK_INPUT;
1817
1818 {
1819 XSetWindowAttributes a;
1820 unsigned long mask;
1821
1822 a.background_pixel = frame->display.x->background_pixel;
1823 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1824 | ButtonMotionMask | PointerMotionHintMask
1825 | ExposureMask);
1826 a.cursor = x_vertical_scroll_bar_cursor;
1827
1828 mask = (CWBackPixel | CWEventMask | CWCursor);
1829
1830 SET_SCROLL_BAR_X_WINDOW
1831 (bar,
1832 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1833
1834 /* Position and size of scroll bar. */
1835 left, top, width, height,
1836
1837 /* Border width, depth, class, and visual. */
1838 0, CopyFromParent, CopyFromParent, CopyFromParent,
1839
1840 /* Attributes. */
1841 mask, &a));
1842 }
1843
1844 XSET (bar->window, Lisp_Window, window);
1845 XSET (bar->top, Lisp_Int, top);
1846 XSET (bar->left, Lisp_Int, left);
1847 XSET (bar->width, Lisp_Int, width);
1848 XSET (bar->height, Lisp_Int, height);
1849 XSET (bar->start, Lisp_Int, 0);
1850 XSET (bar->end, Lisp_Int, 0);
1851 bar->dragging = Qnil;
1852
1853 /* Add bar to its frame's list of scroll bars. */
1854 bar->next = FRAME_SCROLL_BARS (frame);
1855 bar->prev = Qnil;
1856 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1857 if (! NILP (bar->next))
1858 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1859
1860 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1861
1862 UNBLOCK_INPUT;
1863
1864 return bar;
1865 }
1866
1867 /* Draw BAR's handle in the proper position.
1868 If the handle is already drawn from START to END, don't bother
1869 redrawing it, unless REBUILD is non-zero; in that case, always
1870 redraw it. (REBUILD is handy for drawing the handle after expose
1871 events.)
1872
1873 Normally, we want to constrain the start and end of the handle to
1874 fit inside its rectangle, but if the user is dragging the scroll bar
1875 handle, we want to let them drag it down all the way, so that the
1876 bar's top is as far down as it goes; otherwise, there's no way to
1877 move to the very end of the buffer. */
1878 static void
1879 x_scroll_bar_set_handle (bar, start, end, rebuild)
1880 struct scroll_bar *bar;
1881 int start, end;
1882 int rebuild;
1883 {
1884 int dragging = ! NILP (bar->dragging);
1885 Window w = SCROLL_BAR_X_WINDOW (bar);
1886 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1887
1888 /* If the display is already accurate, do nothing. */
1889 if (! rebuild
1890 && start == XINT (bar->start)
1891 && end == XINT (bar->end))
1892 return;
1893
1894 BLOCK_INPUT;
1895
1896 {
1897 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1898 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1899 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
1900
1901 /* Make sure the values are reasonable, and try to preserve
1902 the distance between start and end. */
1903 {
1904 int length = end - start;
1905
1906 if (start < 0)
1907 start = 0;
1908 else if (start > top_range)
1909 start = top_range;
1910 end = start + length;
1911
1912 if (end < start)
1913 end = start;
1914 else if (end > top_range && ! dragging)
1915 end = top_range;
1916 }
1917
1918 /* Store the adjusted setting in the scroll bar. */
1919 XSET (bar->start, Lisp_Int, start);
1920 XSET (bar->end, Lisp_Int, end);
1921
1922 /* Clip the end position, just for display. */
1923 if (end > top_range)
1924 end = top_range;
1925
1926 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1927 below top positions, to make sure the handle is always at least
1928 that many pixels tall. */
1929 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
1930
1931 /* Draw the empty space above the handle. Note that we can't clear
1932 zero-height areas; that means "clear to end of window." */
1933 if (0 < start)
1934 XClearArea (x_current_display, w,
1935
1936 /* x, y, width, height, and exposures. */
1937 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1938 VERTICAL_SCROLL_BAR_TOP_BORDER,
1939 inside_width, start,
1940 False);
1941
1942 /* Draw the handle itself. */
1943 XFillRectangle (x_current_display, w, gc,
1944
1945 /* x, y, width, height */
1946 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1947 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
1948 inside_width, end - start);
1949
1950
1951 /* Draw the empty space below the handle. Note that we can't
1952 clear zero-height areas; that means "clear to end of window." */
1953 if (end < inside_height)
1954 XClearArea (x_current_display, w,
1955
1956 /* x, y, width, height, and exposures. */
1957 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1958 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
1959 inside_width, inside_height - end,
1960 False);
1961
1962 }
1963
1964 UNBLOCK_INPUT;
1965 }
1966
1967 /* Move a scroll bar around on the screen, to accomodate changing
1968 window configurations. */
1969 static void
1970 x_scroll_bar_move (bar, top, left, width, height)
1971 struct scroll_bar *bar;
1972 int top, left, width, height;
1973 {
1974 BLOCK_INPUT;
1975
1976 {
1977 XWindowChanges wc;
1978 unsigned int mask = 0;
1979
1980 wc.x = left;
1981 wc.y = top;
1982 wc.width = width;
1983 wc.height = height;
1984
1985 if (left != XINT (bar->left)) mask |= CWX;
1986 if (top != XINT (bar->top)) mask |= CWY;
1987 if (width != XINT (bar->width)) mask |= CWWidth;
1988 if (height != XINT (bar->height)) mask |= CWHeight;
1989
1990 if (mask)
1991 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
1992 mask, &wc);
1993 }
1994
1995 XSET (bar->left, Lisp_Int, left);
1996 XSET (bar->top, Lisp_Int, top);
1997 XSET (bar->width, Lisp_Int, width);
1998 XSET (bar->height, Lisp_Int, height);
1999
2000 UNBLOCK_INPUT;
2001 }
2002
2003 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2004 to nil. */
2005 static void
2006 x_scroll_bar_remove (bar)
2007 struct scroll_bar *bar;
2008 {
2009 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2010
2011 BLOCK_INPUT;
2012
2013 /* Destroy the window. */
2014 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2015
2016 /* Disassociate this scroll bar from its window. */
2017 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2018
2019 UNBLOCK_INPUT;
2020 }
2021
2022 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2023 that we are displaying PORTION characters out of a total of WHOLE
2024 characters, starting at POSITION. If WINDOW has no scroll bar,
2025 create one. */
2026 static void
2027 XTset_vertical_scroll_bar (window, portion, whole, position)
2028 struct window *window;
2029 int portion, whole, position;
2030 {
2031 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2032 int top = XINT (window->top);
2033 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2034 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2035
2036 /* Where should this scroll bar be, pixelwise? */
2037 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2038 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2039 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2040 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2041
2042 struct scroll_bar *bar;
2043
2044 /* Does the scroll bar exist yet? */
2045 if (NILP (window->vertical_scroll_bar))
2046 bar = x_scroll_bar_create (window,
2047 pixel_top, pixel_left,
2048 pixel_width, pixel_height);
2049 else
2050 {
2051 /* It may just need to be moved and resized. */
2052 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2053 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2054 }
2055
2056 /* Set the scroll bar's current state, unless we're currently being
2057 dragged. */
2058 if (NILP (bar->dragging))
2059 {
2060 int top_range =
2061 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2062
2063 if (whole == 0)
2064 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2065 else
2066 {
2067 int start = (position * top_range) / whole;
2068 int end = ((position + portion) * top_range) / whole;
2069
2070 x_scroll_bar_set_handle (bar, start, end, 0);
2071 }
2072 }
2073
2074 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2075 }
2076
2077
2078 /* The following three hooks are used when we're doing a thorough
2079 redisplay of the frame. We don't explicitly know which scroll bars
2080 are going to be deleted, because keeping track of when windows go
2081 away is a real pain - "Can you say set-window-configuration, boys
2082 and girls?" Instead, we just assert at the beginning of redisplay
2083 that *all* scroll bars are to be removed, and then save a scroll bar
2084 from the fiery pit when we actually redisplay its window. */
2085
2086 /* Arrange for all scroll bars on FRAME to be removed at the next call
2087 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2088 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2089 static void
2090 XTcondemn_scroll_bars (frame)
2091 FRAME_PTR frame;
2092 {
2093 /* The condemned list should be empty at this point; if it's not,
2094 then the rest of Emacs isn't using the condemn/redeem/judge
2095 protocol correctly. */
2096 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2097 abort ();
2098
2099 /* Move them all to the "condemned" list. */
2100 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2101 FRAME_SCROLL_BARS (frame) = Qnil;
2102 }
2103
2104 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2105 Note that WINDOW isn't necessarily condemned at all. */
2106 static void
2107 XTredeem_scroll_bar (window)
2108 struct window *window;
2109 {
2110 struct scroll_bar *bar;
2111
2112 /* We can't redeem this window's scroll bar if it doesn't have one. */
2113 if (NILP (window->vertical_scroll_bar))
2114 abort ();
2115
2116 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2117
2118 /* Unlink it from the condemned list. */
2119 {
2120 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2121
2122 if (NILP (bar->prev))
2123 {
2124 /* If the prev pointer is nil, it must be the first in one of
2125 the lists. */
2126 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2127 /* It's not condemned. Everything's fine. */
2128 return;
2129 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2130 window->vertical_scroll_bar))
2131 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2132 else
2133 /* If its prev pointer is nil, it must be at the front of
2134 one or the other! */
2135 abort ();
2136 }
2137 else
2138 XSCROLL_BAR (bar->prev)->next = bar->next;
2139
2140 if (! NILP (bar->next))
2141 XSCROLL_BAR (bar->next)->prev = bar->prev;
2142
2143 bar->next = FRAME_SCROLL_BARS (f);
2144 bar->prev = Qnil;
2145 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2146 if (! NILP (bar->next))
2147 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2148 }
2149 }
2150
2151 /* Remove all scroll bars on FRAME that haven't been saved since the
2152 last call to `*condemn_scroll_bars_hook'. */
2153 static void
2154 XTjudge_scroll_bars (f)
2155 FRAME_PTR f;
2156 {
2157 Lisp_Object bar, next;
2158
2159 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2160
2161 /* Clear out the condemned list now so we won't try to process any
2162 more events on the hapless scroll bars. */
2163 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2164
2165 for (; ! NILP (bar); bar = next)
2166 {
2167 struct scroll_bar *b = XSCROLL_BAR (bar);
2168
2169 x_scroll_bar_remove (b);
2170
2171 next = b->next;
2172 b->next = b->prev = Qnil;
2173 }
2174
2175 /* Now there should be no references to the condemned scroll bars,
2176 and they should get garbage-collected. */
2177 }
2178
2179
2180 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2181
2182 This may be called from a signal handler, so we have to ignore GC
2183 mark bits. */
2184 static void
2185 x_scroll_bar_expose (bar, event)
2186 struct scroll_bar *bar;
2187 XEvent *event;
2188 {
2189 Window w = SCROLL_BAR_X_WINDOW (bar);
2190 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2191
2192 BLOCK_INPUT;
2193
2194 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2195
2196 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2197 XDrawRectangle (x_current_display, w, gc,
2198
2199 /* x, y, width, height */
2200 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2201
2202 /* Draw another line to make the extra-thick border on the right. */
2203 XFillRectangle (x_current_display, w, gc,
2204
2205 /* x, y, width, height */
2206 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2207
2208 UNBLOCK_INPUT;
2209 }
2210
2211 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2212 is set to something other than no_event, it is enqueued.
2213
2214 This may be called from a signal handler, so we have to ignore GC
2215 mark bits. */
2216 static void
2217 x_scroll_bar_handle_click (bar, event, emacs_event)
2218 struct scroll_bar *bar;
2219 XEvent *event;
2220 struct input_event *emacs_event;
2221 {
2222 if (XGCTYPE (bar->window) != Lisp_Window)
2223 abort ();
2224
2225 emacs_event->kind = scroll_bar_click;
2226 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2227 emacs_event->modifiers =
2228 (x_convert_modifiers (event->xbutton.state)
2229 | (event->type == ButtonRelease
2230 ? up_modifier
2231 : down_modifier));
2232 emacs_event->frame_or_window = bar->window;
2233 emacs_event->timestamp = event->xbutton.time;
2234 {
2235 int internal_height =
2236 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2237 int top_range =
2238 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2239 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2240
2241 if (y < 0) y = 0;
2242 if (y > top_range) y = top_range;
2243
2244 if (y < XINT (bar->start))
2245 emacs_event->part = scroll_bar_above_handle;
2246 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2247 emacs_event->part = scroll_bar_handle;
2248 else
2249 emacs_event->part = scroll_bar_below_handle;
2250
2251 /* If the user has just clicked on the handle, record where they're
2252 holding it. */
2253 if (event->type == ButtonPress
2254 && emacs_event->part == scroll_bar_handle)
2255 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2256
2257 /* If the user has released the handle, set it to its final position. */
2258 if (event->type == ButtonRelease
2259 && ! NILP (bar->dragging))
2260 {
2261 int new_start = y - XINT (bar->dragging);
2262 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2263
2264 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2265 bar->dragging = Qnil;
2266 }
2267
2268 /* Clicks on the handle are always reported as occuring at the top of
2269 the handle. */
2270 if (emacs_event->part == scroll_bar_handle)
2271 emacs_event->x = bar->start;
2272 else
2273 XSET (emacs_event->x, Lisp_Int, y);
2274
2275 XSET (emacs_event->y, Lisp_Int, top_range);
2276 }
2277 }
2278
2279 /* Handle some mouse motion while someone is dragging the scroll bar.
2280
2281 This may be called from a signal handler, so we have to ignore GC
2282 mark bits. */
2283 static void
2284 x_scroll_bar_note_movement (bar, event)
2285 struct scroll_bar *bar;
2286 XEvent *event;
2287 {
2288 last_mouse_movement_time = event->xmotion.time;
2289
2290 mouse_moved = 1;
2291 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2292
2293 /* If we're dragging the bar, display it. */
2294 if (! GC_NILP (bar->dragging))
2295 {
2296 /* Where should the handle be now? */
2297 int new_start = event->xmotion.y - XINT (bar->dragging);
2298
2299 if (new_start != XINT (bar->start))
2300 {
2301 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2302
2303 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2304 }
2305 }
2306
2307 /* Call XQueryPointer so we'll get an event the next time the mouse
2308 moves and we can see *still* on the same position. */
2309 {
2310 int dummy;
2311
2312 XQueryPointer (event->xmotion.display, event->xmotion.window,
2313 (Window *) &dummy, (Window *) &dummy,
2314 &dummy, &dummy, &dummy, &dummy,
2315 (unsigned int *) &dummy);
2316 }
2317 }
2318
2319 /* Return information to the user about the current position of the mouse
2320 on the scroll bar. */
2321 static void
2322 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2323 FRAME_PTR *f;
2324 Lisp_Object *bar_window;
2325 enum scroll_bar_part *part;
2326 Lisp_Object *x, *y;
2327 unsigned long *time;
2328 {
2329 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2330 int win_x, win_y;
2331
2332 BLOCK_INPUT;
2333
2334 /* Get the mouse's position relative to the scroll bar window, and
2335 report that. */
2336 {
2337 Window dummy_window;
2338 int dummy_coord;
2339 unsigned int dummy_mask;
2340
2341 if (! XQueryPointer (x_current_display,
2342 SCROLL_BAR_X_WINDOW (bar),
2343
2344 /* Root, child, root x and root y. */
2345 &dummy_window, &dummy_window,
2346 &dummy_coord, &dummy_coord,
2347
2348 /* Position relative to scroll bar. */
2349 &win_x, &win_y,
2350
2351 /* Mouse buttons and modifier keys. */
2352 &dummy_mask))
2353 {
2354 *f = 0;
2355 goto done;
2356 }
2357 }
2358
2359 {
2360 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2361 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2362
2363 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2364
2365 if (! NILP (bar->dragging))
2366 win_y -= XINT (bar->dragging);
2367
2368 if (win_y < 0)
2369 win_y = 0;
2370 if (win_y > top_range)
2371 win_y = top_range;
2372
2373 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2374 *bar_window = bar->window;
2375
2376 if (! NILP (bar->dragging))
2377 *part = scroll_bar_handle;
2378 else if (win_y < XINT (bar->start))
2379 *part = scroll_bar_above_handle;
2380 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2381 *part = scroll_bar_handle;
2382 else
2383 *part = scroll_bar_below_handle;
2384
2385 XSET (*x, Lisp_Int, win_y);
2386 XSET (*y, Lisp_Int, top_range);
2387 *time = last_mouse_movement_time;
2388 }
2389
2390 mouse_moved = 0;
2391 last_mouse_scroll_bar = Qnil;
2392
2393 done:
2394 UNBLOCK_INPUT;
2395 }
2396
2397
2398 /* The screen has been cleared so we may have changed foreground or
2399 background colors, and the scroll bars may need to be redrawn.
2400 Clear out the scroll bars, and ask for expose events, so we can
2401 redraw them. */
2402
2403 x_scroll_bar_clear (f)
2404 FRAME_PTR f;
2405 {
2406 Lisp_Object bar;
2407
2408 for (bar = FRAME_SCROLL_BARS (f);
2409 XTYPE (bar) == Lisp_Vector;
2410 bar = XSCROLL_BAR (bar)->next)
2411 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2412 0, 0, 0, 0, True);
2413 }
2414
2415
2416 \f
2417 /* The main X event-reading loop - XTread_socket. */
2418
2419 /* Timestamp of enter window event. This is only used by XTread_socket,
2420 but we have to put it out here, since static variables within functions
2421 sometimes don't work. */
2422 static Time enter_timestamp;
2423
2424 /* This holds the state XLookupString needs to implement dead keys
2425 and other tricks known as "compose processing". _X Window System_
2426 says that a portable program can't use this, but Stephen Gildea assures
2427 me that letting the compiler initialize it to zeros will work okay.
2428
2429 This must be defined outside of XTread_socket, for the same reasons
2430 given for enter_timestamp, above. */
2431 static XComposeStatus compose_status;
2432
2433 /* Communication with window managers. */
2434 Atom Xatom_wm_protocols;
2435
2436 /* Kinds of protocol things we may receive. */
2437 Atom Xatom_wm_take_focus;
2438 Atom Xatom_wm_save_yourself;
2439 Atom Xatom_wm_delete_window;
2440
2441 /* Other WM communication */
2442 Atom Xatom_wm_configure_denied; /* When our config request is denied */
2443 Atom Xatom_wm_window_moved; /* When the WM moves us. */
2444
2445 /* Window manager communication. */
2446 Atom Xatom_wm_change_state;
2447
2448 /* Record the last 100 characters stored
2449 to help debug the loss-of-chars-during-GC problem. */
2450 int temp_index;
2451 short temp_buffer[100];
2452
2453 /* Read events coming from the X server.
2454 This routine is called by the SIGIO handler.
2455 We return as soon as there are no more events to be read.
2456
2457 Events representing keys are stored in buffer BUFP,
2458 which can hold up to NUMCHARS characters.
2459 We return the number of characters stored into the buffer,
2460 thus pretending to be `read'.
2461
2462 WAITP is nonzero if we should block until input arrives.
2463 EXPECTED is nonzero if the caller knows input is available. */
2464
2465 int
2466 XTread_socket (sd, bufp, numchars, waitp, expected)
2467 register int sd;
2468 register struct input_event *bufp;
2469 register int numchars;
2470 int waitp;
2471 int expected;
2472 {
2473 int count = 0;
2474 int nbytes = 0;
2475 int mask;
2476 int items_pending; /* How many items are in the X queue. */
2477 XEvent event;
2478 struct frame *f;
2479 int event_found;
2480 int prefix;
2481 Lisp_Object part;
2482
2483 if (x_input_blocked)
2484 {
2485 x_pending_input = 1;
2486 return -1;
2487 }
2488
2489 x_pending_input = 0;
2490 BLOCK_INPUT;
2491
2492 if (numchars <= 0)
2493 abort (); /* Don't think this happens. */
2494
2495 #ifdef FIOSNBIO
2496 /* If available, Xlib uses FIOSNBIO to make the socket
2497 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2498 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2499 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2500 fcntl (fileno (stdin), F_SETFL, 0);
2501 #endif /* ! defined (FIOSNBIO) */
2502
2503 #ifndef SIGIO
2504 #ifndef HAVE_SELECT
2505 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2506 {
2507 extern int read_alarm_should_throw;
2508 read_alarm_should_throw = 1;
2509 XPeekEvent (XDISPLAY &event);
2510 read_alarm_should_throw = 0;
2511 }
2512 #endif /* HAVE_SELECT */
2513 #endif /* SIGIO */
2514
2515 while (XStuffPending () != 0)
2516 {
2517 XNextEvent (XDISPLAY &event);
2518 event_found = 1;
2519
2520 switch (event.type)
2521 {
2522 #ifdef HAVE_X11
2523 case ClientMessage:
2524 {
2525 if (event.xclient.message_type == Xatom_wm_protocols
2526 && event.xclient.format == 32)
2527 {
2528 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2529 {
2530 f = x_window_to_frame (event.xclient.window);
2531 if (f)
2532 x_focus_on_frame (f);
2533 /* Not certain about handling scroll bars here */
2534 }
2535 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2536 {
2537 /* Save state modify the WM_COMMAND property to
2538 something which can reinstate us. This notifies
2539 the session manager, who's looking for such a
2540 PropertyNotify. Can restart processing when
2541 a keyboard or mouse event arrives. */
2542 if (numchars > 0)
2543 {
2544 }
2545 }
2546 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2547 {
2548 struct frame *f = x_window_to_frame (event.xclient.window);
2549
2550 if (f)
2551 if (numchars > 0)
2552 {
2553 }
2554 }
2555 }
2556 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2557 {
2558 }
2559 else if (event.xclient.message_type == Xatom_wm_window_moved)
2560 {
2561 int new_x, new_y;
2562
2563 new_x = event.xclient.data.s[0];
2564 new_y = event.xclient.data.s[1];
2565 }
2566 }
2567 break;
2568
2569 #ifdef NEW_SELECTIONS
2570 case SelectionNotify:
2571 x_handle_selection_notify (&event);
2572 break;
2573 #endif
2574
2575 case SelectionClear: /* Someone has grabbed ownership. */
2576 #ifdef NEW_SELECTIONS
2577 {
2578 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2579
2580 if (numchars == 0)
2581 abort ();
2582
2583 bufp->kind = selection_clear_event;
2584 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2585 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2586 SELECTION_EVENT_TIME (bufp) = eventp->time;
2587 bufp++;
2588
2589 count += 1;
2590 numchars -= 1;
2591 }
2592 #else
2593 x_disown_selection (event.xselectionclear.window,
2594 event.xselectionclear.selection,
2595 event.xselectionclear.time);
2596 #endif
2597 break;
2598
2599 case SelectionRequest: /* Someone wants our selection. */
2600 #ifdef NEW_SELECTIONS
2601 {
2602 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2603
2604 if (numchars == 0)
2605 abort ();
2606
2607 bufp->kind = selection_request_event;
2608 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2609 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2610 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2611 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2612 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2613 SELECTION_EVENT_TIME (bufp) = eventp->time;
2614 bufp++;
2615
2616 count += 1;
2617 numchars -= 1;
2618 }
2619 #else
2620 x_answer_selection_request (event);
2621 #endif
2622 break;
2623
2624 case PropertyNotify:
2625 #ifdef NEW_SELECTIONS
2626 x_handle_property_notify (&event);
2627 #else
2628 /* If we're being told about a root window property, then it's
2629 a cut buffer change. */
2630 if (event.xproperty.window == ROOT_WINDOW)
2631 x_invalidate_cut_buffer_cache (&event.xproperty);
2632
2633 /* Otherwise, we're probably handling an incremental
2634 selection transmission. */
2635 else
2636 {
2637 /* If we were to do this synchronously, there'd be no worry
2638 about re-selecting. */
2639 x_send_incremental (event);
2640 }
2641 #endif
2642 break;
2643
2644 case Expose:
2645 f = x_window_to_frame (event.xexpose.window);
2646 if (f)
2647 {
2648 if (f->async_visible == 0)
2649 {
2650 f->async_visible = 1;
2651 f->async_iconified = 0;
2652 SET_FRAME_GARBAGED (f);
2653 }
2654 else
2655 {
2656 dumprectangle (x_window_to_frame (event.xexpose.window),
2657 event.xexpose.x, event.xexpose.y,
2658 event.xexpose.width, event.xexpose.height);
2659 }
2660 }
2661 else
2662 {
2663 struct scroll_bar *bar
2664 = x_window_to_scroll_bar (event.xexpose.window);
2665
2666 if (bar)
2667 x_scroll_bar_expose (bar, &event);
2668 }
2669 break;
2670
2671 case GraphicsExpose: /* This occurs when an XCopyArea's
2672 source area was obscured or not
2673 available.*/
2674 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2675 if (f)
2676 {
2677 dumprectangle (f,
2678 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2679 event.xgraphicsexpose.width,
2680 event.xgraphicsexpose.height);
2681 }
2682 break;
2683
2684 case NoExpose: /* This occurs when an XCopyArea's
2685 source area was completely
2686 available */
2687 break;
2688 #else /* ! defined (HAVE_X11) */
2689 case ExposeWindow:
2690 if (event.subwindow != 0)
2691 break; /* duplicate event */
2692 f = x_window_to_frame (event.window);
2693 if (event.window == f->display.x->icon_desc)
2694 {
2695 refreshicon (f);
2696 f->async_iconified = 1;
2697 }
2698 if (event.window == FRAME_X_WINDOW (f))
2699 {
2700 /* Say must check all windows' needs_exposure flags. */
2701 expose_all_windows = 1;
2702 f->display.x->needs_exposure = 1;
2703 f->async_visible = 1;
2704 }
2705 break;
2706
2707 case ExposeRegion:
2708 if (event.subwindow != 0)
2709 break; /* duplicate event */
2710 f = x_window_to_frame (event.window);
2711 if (event.window == f->display.x->icon_desc)
2712 {
2713 refreshicon (f);
2714 break;
2715 }
2716 /* If window already needs full redraw, ignore this rectangle. */
2717 if (expose_all_windows && f->display.x->needs_exposure)
2718 break;
2719 /* Put the event on the queue of rectangles to redraw. */
2720 if (enqueue_event (&event, &x_expose_queue))
2721 /* If it is full, we can't record the rectangle,
2722 so redraw this entire window. */
2723 {
2724 /* Say must check all windows' needs_exposure flags. */
2725 expose_all_windows = 1;
2726 f->display.x->needs_exposure = 1;
2727 }
2728 break;
2729
2730 case ExposeCopy:
2731 /* This should happen only when we are expecting it,
2732 in x_read_exposes. */
2733 abort ();
2734 #endif /* ! defined (HAVE_X11) */
2735
2736 #ifdef HAVE_X11
2737 case UnmapNotify:
2738 f = x_window_to_frame (event.xunmap.window);
2739 if (f) /* F may no longer exist if
2740 the frame was deleted. */
2741 {
2742 /* While a frame is unmapped, display generation is
2743 disabled; you don't want to spend time updating a
2744 display that won't ever be seen. */
2745 f->async_visible = 0;
2746 }
2747 break;
2748
2749 case MapNotify:
2750 f = x_window_to_frame (event.xmap.window);
2751 if (f)
2752 {
2753 f->async_visible = 1;
2754 f->async_iconified = 0;
2755
2756 /* wait_reading_process_input will notice this and update
2757 the frame's display structures. */
2758 SET_FRAME_GARBAGED (f);
2759 }
2760 break;
2761
2762 /* Turn off processing if we become fully obscured. */
2763 case VisibilityNotify:
2764 break;
2765
2766 #else /* ! defined (HAVE_X11) */
2767 case UnmapWindow:
2768 f = x_window_to_frame (event.window);
2769 if (event.window == f->display.x->icon_desc)
2770 f->async_iconified = 0;
2771 if (event.window == FRAME_X_WINDOW (f))
2772 f->async_visible = 0;
2773 break;
2774 #endif /* ! defined (HAVE_X11) */
2775
2776 #ifdef HAVE_X11
2777 case KeyPress:
2778 f = x_window_to_frame (event.xkey.window);
2779
2780 if (f != 0)
2781 {
2782 KeySym keysym;
2783 char copy_buffer[80];
2784 int modifiers;
2785
2786 event.xkey.state |= extra_keyboard_modifiers;
2787 modifiers = event.xkey.state;
2788
2789 /* Some keyboards generate different characters
2790 depending on the state of the meta key, in an attempt
2791 to support non-English typists. It would be nice to
2792 keep this functionality somehow, but for now, we will
2793 just clear the meta-key flag to get the 'pure' character. */
2794 event.xkey.state &= ~Mod1Mask;
2795
2796 /* This will have to go some day... */
2797 nbytes =
2798 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2799 &compose_status);
2800
2801 /* Strip off the vendor-specific keysym bit, and take a shot
2802 at recognizing the codes. HP servers have extra keysyms
2803 that fit into the MiscFunctionKey category. */
2804 keysym &= ~(1<<28);
2805
2806 if (numchars > 1)
2807 {
2808 if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
2809 || keysym == XK_Delete
2810 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2811 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
2812 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2813 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
2814 {
2815 if (temp_index == sizeof temp_buffer / sizeof (short))
2816 temp_index = 0;
2817 temp_buffer[temp_index++] = keysym;
2818 bufp->kind = non_ascii_keystroke;
2819 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2820 XSET (bufp->frame_or_window, Lisp_Frame, f);
2821 bufp->modifiers = x_convert_modifiers (modifiers);
2822 bufp->timestamp = event.xkey.time;
2823 bufp++;
2824 count++;
2825 numchars--;
2826 }
2827 else if (numchars > nbytes)
2828 {
2829 register int i;
2830
2831 for (i = 0; i < nbytes; i++)
2832 {
2833 if (temp_index == sizeof temp_buffer / sizeof (short))
2834 temp_index = 0;
2835 temp_buffer[temp_index++] = copy_buffer[i];
2836 bufp->kind = ascii_keystroke;
2837 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2838 XSET (bufp->frame_or_window, Lisp_Frame, f);
2839 bufp->modifiers = x_convert_modifiers (modifiers);
2840 bufp->timestamp = event.xkey.time;
2841 bufp++;
2842 }
2843
2844 count += nbytes;
2845 numchars -= nbytes;
2846 }
2847 else
2848 abort ();
2849 }
2850 else
2851 abort ();
2852 }
2853 break;
2854 #else /* ! defined (HAVE_X11) */
2855 case KeyPressed:
2856 {
2857 register char *where_mapping;
2858
2859 f = x_window_to_frame (event.window);
2860 /* Ignore keys typed on icon windows. */
2861 if (f != 0 && event.window == f->display.x->icon_desc)
2862 break;
2863 where_mapping = XLookupMapping (&event, &nbytes);
2864 /* Nasty fix for arrow keys */
2865 if (!nbytes && IsCursorKey (event.detail & 0xff))
2866 {
2867 switch (event.detail & 0xff)
2868 {
2869 case KC_CURSOR_LEFT:
2870 where_mapping = "\002";
2871 break;
2872 case KC_CURSOR_RIGHT:
2873 where_mapping = "\006";
2874 break;
2875 case KC_CURSOR_UP:
2876 where_mapping = "\020";
2877 break;
2878 case KC_CURSOR_DOWN:
2879 where_mapping = "\016";
2880 break;
2881 }
2882 nbytes = 1;
2883 }
2884 if (numchars - nbytes > 0)
2885 {
2886 register int i;
2887
2888 for (i = 0; i < nbytes; i++)
2889 {
2890 bufp->kind = ascii_keystroke;
2891 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2892 XSET (bufp->time, Lisp_Int, event.xkey.time);
2893 XSET (bufp->frame_or_window, Lisp_Frame, f);
2894 bufp++;
2895 }
2896 count += nbytes;
2897 numchars -= nbytes;
2898 }
2899 }
2900 break;
2901 #endif /* ! defined (HAVE_X11) */
2902
2903 #ifdef HAVE_X11
2904
2905 /* Here's a possible interpretation of the whole
2906 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2907 FocusIn event, you have to get a FocusOut event before you
2908 relinquish the focus. If you haven't received a FocusIn event,
2909 then a mere LeaveNotify is enough to free you. */
2910
2911 case EnterNotify:
2912 f = x_window_to_frame (event.xcrossing.window);
2913
2914 if (event.xcrossing.focus) /* Entered Window */
2915 {
2916 /* Avoid nasty pop/raise loops. */
2917 if (f && (!(f->auto_raise)
2918 || !(f->auto_lower)
2919 || (event.xcrossing.time - enter_timestamp) > 500))
2920 {
2921 x_new_focus_frame (f);
2922 enter_timestamp = event.xcrossing.time;
2923 }
2924 }
2925 else if (f == x_focus_frame)
2926 x_new_focus_frame (0);
2927
2928 break;
2929
2930 case FocusIn:
2931 f = x_window_to_frame (event.xfocus.window);
2932 if (event.xfocus.detail != NotifyPointer)
2933 x_focus_event_frame = f;
2934 if (f)
2935 x_new_focus_frame (f);
2936 break;
2937
2938
2939 case LeaveNotify:
2940 f = x_window_to_frame (event.xcrossing.window);
2941
2942 if (event.xcrossing.focus)
2943 {
2944 if (! x_focus_event_frame)
2945 x_new_focus_frame (0);
2946 else
2947 x_new_focus_frame (f);
2948 }
2949 else
2950 {
2951 if (f == x_focus_event_frame)
2952 x_focus_event_frame = 0;
2953 if (f == x_focus_frame)
2954 x_new_focus_frame (0);
2955 }
2956 break;
2957
2958 case FocusOut:
2959 f = x_window_to_frame (event.xfocus.window);
2960 if (event.xfocus.detail != NotifyPointer
2961 && f == x_focus_event_frame)
2962 x_focus_event_frame = 0;
2963 if (f && f == x_focus_frame)
2964 x_new_focus_frame (0);
2965 break;
2966
2967 #else /* ! defined (HAVE_X11) */
2968
2969 case EnterWindow:
2970 if ((event.detail & 0xFF) == 1)
2971 break; /* Coming from our own subwindow */
2972 if (event.subwindow != 0)
2973 break; /* Entering our own subwindow. */
2974
2975 {
2976 f = x_window_to_frame (event.window);
2977 x_mouse_frame = f;
2978
2979 x_new_focus_frame (f);
2980 }
2981 break;
2982
2983 case LeaveWindow:
2984 if ((event.detail & 0xFF) == 1)
2985 break; /* Entering our own subwindow */
2986 if (event.subwindow != 0)
2987 break; /* Leaving our own subwindow. */
2988
2989 x_mouse_frame = 0;
2990 if (x_focus_frame == 0
2991 && x_input_frame != 0
2992 && x_input_frame == x_window_to_frame (event.window)
2993 && event.window == FRAME_X_WINDOW (x_input_frame))
2994 {
2995 f = x_input_frame;
2996 x_input_frame = 0;
2997 if (f)
2998 frame_unhighlight (f);
2999 }
3000 break;
3001 #endif /* ! defined (HAVE_X11) */
3002
3003 #ifdef HAVE_X11
3004 case MotionNotify:
3005 {
3006 f = x_window_to_frame (event.xmotion.window);
3007 if (f)
3008 note_mouse_movement (f, &event.xmotion);
3009 else
3010 {
3011 struct scroll_bar *bar =
3012 x_window_to_scroll_bar (event.xmotion.window);
3013
3014 if (bar)
3015 x_scroll_bar_note_movement (bar, &event);
3016 }
3017 }
3018 break;
3019
3020 case ConfigureNotify:
3021 f = x_window_to_frame (event.xconfigure.window);
3022 if (f)
3023 {
3024 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3025 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3026
3027 /* Even if the number of character rows and columns has
3028 not changed, the font size may have changed, so we need
3029 to check the pixel dimensions as well. */
3030 if (columns != f->width
3031 || rows != f->height
3032 || event.xconfigure.width != f->display.x->pixel_width
3033 || event.xconfigure.height != f->display.x->pixel_height)
3034 {
3035 change_frame_size (f, rows, columns, 0, 1);
3036 SET_FRAME_GARBAGED (f);
3037 }
3038
3039 f->display.x->pixel_width = event.xconfigure.width;
3040 f->display.x->pixel_height = event.xconfigure.height;
3041 f->display.x->left_pos = event.xconfigure.x;
3042 f->display.x->top_pos = event.xconfigure.y;
3043 }
3044 break;
3045
3046 case ButtonPress:
3047 case ButtonRelease:
3048 {
3049 /* If we decide we want to generate an event to be seen
3050 by the rest of Emacs, we put it here. */
3051 struct input_event emacs_event;
3052 emacs_event.kind = no_event;
3053
3054 f = x_window_to_frame (event.xbutton.window);
3055 if (f)
3056 {
3057 if (!x_focus_frame || (f == x_focus_frame))
3058 construct_mouse_click (&emacs_event,
3059 &event, f);
3060 }
3061 else
3062 {
3063 struct scroll_bar *bar =
3064 x_window_to_scroll_bar (event.xbutton.window);
3065
3066 if (bar)
3067 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3068 }
3069
3070 if (numchars >= 1 && emacs_event.kind != no_event)
3071 {
3072 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3073 bufp++;
3074 count++;
3075 numchars--;
3076 }
3077 }
3078 break;
3079
3080 #else /* ! defined (HAVE_X11) */
3081 case ButtonPressed:
3082 case ButtonReleased:
3083 f = x_window_to_frame (event.window);
3084 if (f)
3085 {
3086 if (event.window == f->display.x->icon_desc)
3087 {
3088 x_make_frame_visible (f);
3089
3090 if (warp_mouse_on_deiconify)
3091 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3092 break;
3093 }
3094 if (event.window == FRAME_X_WINDOW (f))
3095 {
3096 if (f->auto_raise)
3097 x_raise_frame (f);
3098 }
3099 }
3100 enqueue_event (&event, &x_mouse_queue);
3101 if (numchars >= 2)
3102 {
3103 bufp->kind = ascii_keystroke;
3104 bufp->code = (char) 'X' & 037; /* C-x */
3105 XSET (bufp->frame_or_window, Lisp_Frame, f);
3106 XSET (bufp->time, Lisp_Int, event.xkey.time);
3107 bufp++;
3108
3109 bufp->kind = ascii_keystroke;
3110 bufp->code = (char) 0; /* C-@ */
3111 XSET (bufp->frame_or_window, Lisp_Frame, f);
3112 XSET (bufp->time, Lisp_Int, event.xkey.time);
3113 bufp++;
3114
3115 count += 2;
3116 numchars -= 2;
3117 }
3118 break;
3119 #endif /* ! defined (HAVE_X11) */
3120
3121 #ifdef HAVE_X11
3122
3123 case CirculateNotify:
3124 break;
3125 case CirculateRequest:
3126 break;
3127
3128 #endif /* ! defined (HAVE_X11) */
3129
3130 case MappingNotify:
3131 /* Someone has changed the keyboard mapping - update the
3132 local cache. */
3133 switch (event.xmapping.request)
3134 {
3135 case MappingModifier:
3136 x_find_modifier_meanings ();
3137 /* This is meant to fall through. */
3138 case MappingKeyboard:
3139 XRefreshKeyboardMapping (&event.xmapping);
3140 }
3141 break;
3142
3143 default:
3144 break;
3145 }
3146 }
3147
3148 #if 0
3149 #ifdef HAVE_SELECT
3150 if (expected && ! event_found)
3151 {
3152 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3153 there is an EOF condition; in other words, that X has died.
3154 Act as if there had been a hangup. */
3155
3156 int fd = ConnectionNumber (x_current_display);
3157 int mask = 1 << fd;
3158
3159 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3160 (EMACS_TIME) 0)
3161 && !XStuffPending ())
3162 kill (getpid (), SIGHUP);
3163 }
3164 #endif /* ! defined (HAVE_SELECT) */
3165 #endif /* ! 0 */
3166
3167 #ifndef HAVE_X11
3168 if (updating_frame == 0)
3169 x_do_pending_expose ();
3170 #endif
3171
3172 UNBLOCK_INPUT;
3173 return count;
3174 }
3175
3176 #ifndef HAVE_X11
3177 /* Read and process only Expose events
3178 until we get an ExposeCopy event; then return.
3179 This is used in insert/delete line.
3180 We assume input is already blocked. */
3181
3182 static void
3183 x_read_exposes ()
3184 {
3185 struct frame *f;
3186 XKeyPressedEvent event;
3187
3188 while (1)
3189 {
3190 /* while there are more events*/
3191 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3192 switch (event.type)
3193 {
3194 case ExposeWindow:
3195 if (event.subwindow != 0)
3196 break; /* duplicate event */
3197 f = x_window_to_frame (event.window);
3198 if (event.window == f->display.x->icon_desc)
3199 {
3200 refreshicon (f);
3201 break;
3202 }
3203 if (event.window == FRAME_X_WINDOW (f))
3204 {
3205 expose_all_windows = 1;
3206 f->display.x->needs_exposure = 1;
3207 break;
3208 }
3209 break;
3210
3211 case ExposeRegion:
3212 if (event.subwindow != 0)
3213 break; /* duplicate event */
3214 f = x_window_to_frame (event.window);
3215 if (event.window == f->display.x->icon_desc)
3216 {
3217 refreshicon (f);
3218 break;
3219 }
3220 /* If window already needs full redraw, ignore this rectangle. */
3221 if (expose_all_windows && f->display.x->needs_exposure)
3222 break;
3223 /* Put the event on the queue of rectangles to redraw. */
3224 if (enqueue_event (&event, &x_expose_queue))
3225 /* If it is full, we can't record the rectangle,
3226 so redraw this entire window. */
3227 {
3228 /* Say must check all windows' needs_exposure flags. */
3229 expose_all_windows = 1;
3230 f->display.x->needs_exposure = 1;
3231 }
3232 break;
3233
3234 case ExposeCopy:
3235 return;
3236 }
3237 }
3238 }
3239 #endif /* HAVE_X11 */
3240
3241 \f
3242 /* Drawing the cursor. */
3243
3244
3245 /* Draw a hollow box cursor. Don't change the inside of the box. */
3246
3247 static void
3248 x_draw_box (f)
3249 struct frame *f;
3250 {
3251 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3252 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3253 int width = FONT_WIDTH (f->display.x->font);
3254 int height = FONT_HEIGHT (f->display.x->font);
3255
3256 #ifdef HAVE_X11
3257 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3258 f->display.x->cursor_gc,
3259 left, top, width - 1, height - 1);
3260 #else /* ! defined (HAVE_X11) */
3261 XPixSet (FRAME_X_WINDOW (f),
3262 left, top, width, 1,
3263 f->display.x->cursor_pixel);
3264
3265 XPixSet (FRAME_X_WINDOW (f),
3266 left, top, 1, height,
3267 f->display.x->cursor_pixel);
3268
3269 XPixSet (FRAME_X_WINDOW (f),
3270 left+width-1, top, 1, height,
3271 f->display.x->cursor_pixel);
3272
3273 XPixSet (FRAME_X_WINDOW (f),
3274 left, top+height-1, width, 1,
3275 f->display.x->cursor_pixel);
3276 #endif /* ! defined (HAVE_X11) */
3277 }
3278
3279 /* Clear the cursor of frame F to background color,
3280 and mark the cursor as not shown.
3281 This is used when the text where the cursor is
3282 is about to be rewritten. */
3283
3284 static void
3285 clear_cursor (f)
3286 struct frame *f;
3287 {
3288 int mask;
3289
3290 if (! FRAME_VISIBLE_P (f)
3291 || f->phys_cursor_x < 0)
3292 return;
3293
3294 #ifdef HAVE_X11
3295 x_display_cursor (f, 0);
3296 #else /* ! defined (HAVE_X11) */
3297 XPixSet (FRAME_X_WINDOW (f),
3298 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3299 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3300 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3301 f->display.x->background_pixel);
3302 #endif /* ! defined (HAVE_X11) */
3303 f->phys_cursor_x = -1;
3304 }
3305
3306 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3307 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3308 glyph drawn. */
3309
3310 static void
3311 x_draw_single_glyph (f, row, column, glyph, highlight)
3312 struct frame *f;
3313 int row, column;
3314 GLYPH glyph;
3315 int highlight;
3316 {
3317 dumpglyphs (f,
3318 CHAR_TO_PIXEL_COL (f, column),
3319 CHAR_TO_PIXEL_ROW (f, row),
3320 &glyph, 1, highlight, f->display.x->font);
3321 }
3322
3323 static void
3324 x_display_bar_cursor (f, on)
3325 struct frame *f;
3326 int on;
3327 {
3328 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3329
3330 /* This is pointless on invisible frames, and dangerous on garbaged
3331 frames; in the latter case, the frame may be in the midst of
3332 changing its size, and curs_x and curs_y may be off the frame. */
3333 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3334 return;
3335
3336 if (! on && f->phys_cursor_x < 0)
3337 return;
3338
3339 /* If we're not updating, then we want to use the current frame's
3340 cursor position, not our local idea of where the cursor ought to be. */
3341 if (f != updating_frame)
3342 {
3343 curs_x = FRAME_CURSOR_X (f);
3344 curs_y = FRAME_CURSOR_Y (f);
3345 }
3346
3347 /* If there is anything wrong with the current cursor state, remove it. */
3348 if (f->phys_cursor_x >= 0
3349 && (!on
3350 || f->phys_cursor_x != curs_x
3351 || f->phys_cursor_y != curs_y
3352 || f->display.x->current_cursor != bar_cursor))
3353 {
3354 /* Erase the cursor by redrawing the character underneath it. */
3355 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3356 f->phys_cursor_glyph,
3357 current_glyphs->highlight[f->phys_cursor_y]);
3358 f->phys_cursor_x = -1;
3359 }
3360
3361 /* If we now need a cursor in the new place or in the new form, do it so. */
3362 if (on
3363 && (f->phys_cursor_x < 0
3364 || (f->display.x->current_cursor != bar_cursor)))
3365 {
3366 f->phys_cursor_glyph
3367 = ((current_glyphs->enable[curs_y]
3368 && curs_x < current_glyphs->used[curs_y])
3369 ? current_glyphs->glyphs[curs_y][curs_x]
3370 : SPACEGLYPH);
3371 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3372 f->display.x->cursor_gc,
3373 CHAR_TO_PIXEL_COL (f, curs_x),
3374 CHAR_TO_PIXEL_ROW (f, curs_y),
3375 1, FONT_HEIGHT (f->display.x->font));
3376
3377 f->phys_cursor_x = curs_x;
3378 f->phys_cursor_y = curs_y;
3379
3380 f->display.x->current_cursor = bar_cursor;
3381 }
3382
3383 if (updating_frame != f)
3384 XFlushQueue ();
3385 }
3386
3387
3388 /* Turn the displayed cursor of frame F on or off according to ON.
3389 If ON is nonzero, where to put the cursor is specified
3390 by F->cursor_x and F->cursor_y. */
3391
3392 static void
3393 x_display_box_cursor (f, on)
3394 struct frame *f;
3395 int on;
3396 {
3397 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3398
3399 /* This is pointless on invisible frames, and dangerous on garbaged
3400 frames; in the latter case, the frame may be in the midst of
3401 changing its size, and curs_x and curs_y may be off the frame. */
3402 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3403 return;
3404
3405 /* If cursor is off and we want it off, return quickly. */
3406 if (!on && f->phys_cursor_x < 0)
3407 return;
3408
3409 /* If we're not updating, then we want to use the current frame's
3410 cursor position, not our local idea of where the cursor ought to be. */
3411 if (f != updating_frame)
3412 {
3413 curs_x = FRAME_CURSOR_X (f);
3414 curs_y = FRAME_CURSOR_Y (f);
3415 }
3416
3417 /* If cursor is currently being shown and we don't want it to be
3418 or it is in the wrong place,
3419 or we want a hollow box and it's not so, (pout!)
3420 erase it. */
3421 if (f->phys_cursor_x >= 0
3422 && (!on
3423 || f->phys_cursor_x != curs_x
3424 || f->phys_cursor_y != curs_y
3425 || (f->display.x->current_cursor != hollow_box_cursor
3426 && (f != x_highlight_frame))))
3427 {
3428 /* Erase the cursor by redrawing the character underneath it. */
3429 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3430 f->phys_cursor_glyph,
3431 current_glyphs->highlight[f->phys_cursor_y]);
3432 f->phys_cursor_x = -1;
3433 }
3434
3435 /* If we want to show a cursor,
3436 or we want a box cursor and it's not so,
3437 write it in the right place. */
3438 if (on
3439 && (f->phys_cursor_x < 0
3440 || (f->display.x->current_cursor != filled_box_cursor
3441 && f == x_highlight_frame)))
3442 {
3443 f->phys_cursor_glyph
3444 = ((current_glyphs->enable[curs_y]
3445 && curs_x < current_glyphs->used[curs_y])
3446 ? current_glyphs->glyphs[curs_y][curs_x]
3447 : SPACEGLYPH);
3448 if (f != x_highlight_frame)
3449 {
3450 x_draw_box (f);
3451 f->display.x->current_cursor = hollow_box_cursor;
3452 }
3453 else
3454 {
3455 x_draw_single_glyph (f, curs_y, curs_x,
3456 f->phys_cursor_glyph, 2);
3457 f->display.x->current_cursor = filled_box_cursor;
3458 }
3459
3460 f->phys_cursor_x = curs_x;
3461 f->phys_cursor_y = curs_y;
3462 }
3463
3464 if (updating_frame != f)
3465 XFlushQueue ();
3466 }
3467
3468 x_display_cursor (f, on)
3469 struct frame *f;
3470 int on;
3471 {
3472 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3473 x_display_box_cursor (f, on);
3474 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3475 x_display_bar_cursor (f, on);
3476 else
3477 /* Those are the only two we have implemented! */
3478 abort ();
3479 }
3480 \f
3481 /* Icons. */
3482
3483 /* Refresh bitmap kitchen sink icon for frame F
3484 when we get an expose event for it. */
3485
3486 refreshicon (f)
3487 struct frame *f;
3488 {
3489 #ifdef HAVE_X11
3490 /* Normally, the window manager handles this function. */
3491 #else /* ! defined (HAVE_X11) */
3492 int mask;
3493
3494 if (f->display.x->icon_bitmap_flag)
3495 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3496 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3497 icon_bitmap, GXcopy, AllPlanes);
3498 else
3499 {
3500 extern struct frame *selected_frame;
3501 struct Lisp_String *str;
3502 unsigned char *string;
3503
3504 string
3505 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3506
3507 if (f->display.x->icon_label != string)
3508 {
3509 f->display.x->icon_label = string;
3510 XChangeWindow (f->display.x->icon_desc,
3511 XQueryWidth (string, icon_font_info->id) + 10,
3512 icon_font_info->height + 10);
3513 }
3514
3515 XText (f->display.x->icon_desc, 5, 5, string,
3516 str->size, icon_font_info->id,
3517 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3518 }
3519 XFlushQueue ();
3520 #endif /* ! defined (HAVE_X11) */
3521 }
3522
3523 /* Make the x-window of frame F use the gnu icon bitmap. */
3524
3525 int
3526 x_bitmap_icon (f)
3527 struct frame *f;
3528 {
3529 int mask;
3530 Window icon_window;
3531
3532 if (FRAME_X_WINDOW (f) == 0)
3533 return 1;
3534
3535 #ifdef HAVE_X11
3536 if (icon_bitmap)
3537 XFreePixmap (x_current_display, icon_bitmap);
3538
3539 icon_bitmap =
3540 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3541 gnu_bits, gnu_width, gnu_height);
3542 x_wm_set_icon_pixmap (f, icon_bitmap);
3543 f->display.x->icon_bitmap_flag = 1;
3544 #else /* ! defined (HAVE_X11) */
3545 if (f->display.x->icon_desc)
3546 {
3547 XClearIconWindow (FRAME_X_WINDOW (f));
3548 XDestroyWindow (f->display.x->icon_desc);
3549 }
3550
3551 icon_window = XCreateWindow (f->display.x->parent_desc,
3552 0, 0, sink_width, sink_height,
3553 2, WhitePixmap, (Pixmap) NULL);
3554
3555 if (icon_window == 0)
3556 return 1;
3557
3558 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3559 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3560
3561 f->display.x->icon_desc = icon_window;
3562 f->display.x->icon_bitmap_flag = 1;
3563
3564 if (icon_bitmap == 0)
3565 icon_bitmap
3566 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3567 #endif /* ! defined (HAVE_X11) */
3568
3569 return 0;
3570 }
3571
3572
3573 /* Make the x-window of frame F use a rectangle with text. */
3574
3575 int
3576 x_text_icon (f, icon_name)
3577 struct frame *f;
3578 char *icon_name;
3579 {
3580 #ifndef HAVE_X11
3581 int mask;
3582 int width;
3583 Window icon_window;
3584 char *X_DefaultValue;
3585 Bitmap b1;
3586
3587 #ifndef WhitePixel
3588 #define WhitePixel 1
3589 #endif /* WhitePixel */
3590
3591 #ifndef BlackPixel
3592 #define BlackPixel 0
3593 #endif /* BlackPixel */
3594 #endif /* HAVE_X11 */
3595
3596 if (FRAME_X_WINDOW (f) == 0)
3597 return 1;
3598
3599 #ifdef HAVE_X11
3600 if (icon_name)
3601 f->display.x->icon_label = icon_name;
3602 else
3603 if (! f->display.x->icon_label)
3604 f->display.x->icon_label = " *emacs* ";
3605
3606 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3607 (char *) f->display.x->icon_label);
3608
3609 f->display.x->icon_bitmap_flag = 0;
3610 x_wm_set_icon_pixmap (f, 0);
3611 #else /* ! defined (HAVE_X11) */
3612 if (icon_font_info == 0)
3613 icon_font_info
3614 = XGetFont (XGetDefault (XDISPLAY
3615 (char *) XSTRING (Vinvocation_name)->data,
3616 "BodyFont"));
3617
3618 if (f->display.x->icon_desc)
3619 {
3620 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3621 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3622 }
3623
3624 if (icon_name)
3625 f->display.x->icon_label = (unsigned char *) icon_name;
3626 else
3627 if (! f->display.x->icon_label)
3628 f->display.x->icon_label = XSTRING (f->name)->data;
3629
3630 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3631 icon_window = XCreateWindow (f->display.x->parent_desc,
3632 f->display.x->left_pos,
3633 f->display.x->top_pos,
3634 width + 10, icon_font_info->height + 10,
3635 2, BlackPixmap, WhitePixmap);
3636
3637 if (icon_window == 0)
3638 return 1;
3639
3640 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3641 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3642
3643 f->display.x->icon_desc = icon_window;
3644 f->display.x->icon_bitmap_flag = 0;
3645 f->display.x->icon_label = 0;
3646 #endif /* ! defined (HAVE_X11) */
3647
3648 return 0;
3649 }
3650 \f
3651 /* Handling X errors. */
3652
3653 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3654 X server's connection, or an error reported via the X protocol. */
3655
3656 static SIGTYPE
3657 x_connection_closed ()
3658 {
3659 if (_Xdebug)
3660 abort ();
3661
3662 shut_down_emacs (0);
3663
3664 exit (70);
3665 }
3666
3667 /* An X error handler which prints an error message and then kills
3668 Emacs. This is what's normally installed as Xlib's handler for
3669 protocol errors. */
3670 static int
3671 x_error_quitter (display, error)
3672 Display *display;
3673 XErrorEvent *error;
3674 {
3675 char buf[256];
3676
3677 /* Note that there is no real way portable across R3/R4 to get the
3678 original error handler. */
3679
3680 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3681 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3682 buf, error->request_code);
3683
3684 /* While we're testing Emacs 19, we'll just dump core whenever we
3685 get an X error, so we can figure out why it happened. */
3686 abort ();
3687
3688 x_connection_closed ();
3689 }
3690
3691 /* A handler for X IO errors which prints an error message and then
3692 kills Emacs. This is what is always installed as Xlib's handler
3693 for I/O errors. */
3694 static int
3695 x_io_error_quitter (display)
3696 Display *display;
3697 {
3698 fprintf (stderr, "Connection to X server %s lost.\n",
3699 XDisplayName (DisplayString (display)));
3700
3701 /* While we're testing Emacs 19, we'll just dump core whenever we
3702 get an X error, so we can figure out why it happened. */
3703 abort ();
3704
3705 x_connection_closed ();
3706 }
3707
3708 /* A buffer for storing X error messages. */
3709 static char (*x_caught_error_message)[200];
3710
3711 /* An X error handler which stores the error message in
3712 x_caught_error_message. This is what's installed when
3713 x_catch_errors is in effect. */
3714 static int
3715 x_error_catcher (display, error)
3716 Display *display;
3717 XErrorEvent *error;
3718 {
3719 XGetErrorText (display, error->error_code,
3720 *x_caught_error_message, sizeof (*x_caught_error_message));
3721 }
3722
3723
3724 /* Begin trapping X errors.
3725
3726 After calling this function, X protocol errors no longer cause
3727 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3728
3729 Calling x_check_errors signals an Emacs error if an X error has
3730 occurred since the last call to x_catch_errors or x_check_errors.
3731
3732 Calling x_uncatch_errors resumes the normal error handling. */
3733
3734 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3735
3736 void
3737 x_catch_errors ()
3738 {
3739 /* Make sure any errors from previous requests have been dealt with. */
3740 XSync (x_current_display, False);
3741
3742 /* Set up the error buffer. */
3743 x_caught_error_message =
3744 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
3745 (*x_caught_error_message)[0] = '\0';
3746
3747 /* Install our little error handler. */
3748 XHandleError (x_error_catcher);
3749 }
3750
3751 /* If any X protocol errors have arrived since the last call to
3752 x_catch_errors or x_check_errors, signal an Emacs error using
3753 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3754 void
3755 x_check_errors (format)
3756 char *format;
3757 {
3758 /* Make sure to catch any errors incurred so far. */
3759 XSync (x_current_display, False);
3760
3761 if ((*x_caught_error_message)[0])
3762 {
3763 char buf[256];
3764
3765 sprintf (buf, format, *x_caught_error_message);
3766 free (x_caught_error_message);
3767
3768 x_uncatch_errors ();
3769 error (buf);
3770 }
3771 }
3772
3773 void
3774 x_uncatch_errors ()
3775 {
3776 free (x_caught_error_message);
3777 XHandleError (x_error_quitter);
3778 }
3779
3780 #if 0
3781 static unsigned int x_wire_count;
3782 x_trace_wire ()
3783 {
3784 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3785 }
3786 #endif /* ! 0 */
3787
3788 \f
3789 /* Changing the font of the frame. */
3790
3791 /* Set the font of the x-window specified by frame F
3792 to the font named NEWNAME. This is safe to use
3793 even before F has an actual x-window. */
3794
3795 #ifdef HAVE_X11
3796
3797 /* A table of all the fonts we have already loaded. */
3798 static XFontStruct **x_font_table;
3799
3800 /* The current capacity of x_font_table. */
3801 static int x_font_table_size;
3802
3803 /* The number of fonts actually stored in x_font_table.
3804 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3805 0 <= n_fonts <= x_font_table_size. */
3806 static int n_fonts;
3807
3808 x_new_font (f, fontname)
3809 struct frame *f;
3810 register char *fontname;
3811 {
3812 XFontStruct *temp;
3813 int already_loaded;
3814 int n_matching_fonts;
3815 XFontStruct *font_info;
3816 char **font_names;
3817
3818 /* Get a list of all the fonts that match this name. Once we
3819 have a list of matching fonts, we compare them against the fonts
3820 we already have by comparing font ids. */
3821 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3822 1024, &n_matching_fonts,
3823 &font_info);
3824 /* If the server couldn't find any fonts whose named matched fontname,
3825 return an error code. */
3826 if (n_matching_fonts == 0)
3827 return 1;
3828
3829 /* See if we've already loaded a matching font. */
3830 {
3831 int i, j;
3832
3833 already_loaded = 0;
3834 for (i = 0; i < n_fonts; i++)
3835 for (j = 0; j < n_matching_fonts; j++)
3836 if (x_font_table[i]->fid == font_info[j].fid)
3837 {
3838 already_loaded = i;
3839 goto found_font;
3840 }
3841 }
3842 found_font:
3843
3844 /* If we have, just return it from the table. */
3845 if (already_loaded)
3846 f->display.x->font = x_font_table[already_loaded];
3847
3848 /* Otherwise, load the font and add it to the table. */
3849 else
3850 {
3851 XFontStruct *font;
3852
3853 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3854 if (! font)
3855 return 1;
3856
3857 /* Do we need to create the table? */
3858 if (x_font_table_size == 0)
3859 {
3860 x_font_table_size = 16;
3861 x_font_table
3862 = (XFontStruct **) xmalloc (x_font_table_size
3863 * sizeof (x_font_table[0]));
3864 }
3865 /* Do we need to grow the table? */
3866 else if (n_fonts >= x_font_table_size)
3867 {
3868 x_font_table_size *= 2;
3869 x_font_table
3870 = (XFontStruct **) xrealloc (x_font_table,
3871 (x_font_table_size
3872 * sizeof (x_font_table[0])));
3873 }
3874
3875 f->display.x->font = x_font_table[n_fonts++] = font;
3876 }
3877
3878 /* Free the information from XListFontsWithInfo. The data
3879 we actually retain comes from XLoadQueryFont. */
3880 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3881
3882 /* Now make the frame display the given font. */
3883 if (FRAME_X_WINDOW (f) != 0)
3884 {
3885 XSetFont (x_current_display, f->display.x->normal_gc,
3886 f->display.x->font->fid);
3887 XSetFont (x_current_display, f->display.x->reverse_gc,
3888 f->display.x->font->fid);
3889 XSetFont (x_current_display, f->display.x->cursor_gc,
3890 f->display.x->font->fid);
3891
3892 x_set_window_size (f, f->width, f->height);
3893 }
3894
3895 return 0;
3896 }
3897 #else /* ! defined (HAVE_X11) */
3898 x_new_font (f, newname)
3899 struct frame *f;
3900 register char *newname;
3901 {
3902 FONT_TYPE *temp;
3903 int mask;
3904
3905 temp = XGetFont (newname);
3906 if (temp == (FONT_TYPE *) 0)
3907 return 1;
3908
3909 if (f->display.x->font)
3910 XLoseFont (f->display.x->font);
3911
3912 f->display.x->font = temp;
3913
3914 if (FRAME_X_WINDOW (f) != 0)
3915 x_set_window_size (f, f->width, f->height);
3916
3917 return 0;
3918 }
3919 #endif /* ! defined (HAVE_X11) */
3920 \f
3921 /* X Window sizes and positions. */
3922
3923 x_calc_absolute_position (f)
3924 struct frame *f;
3925 {
3926 #ifdef HAVE_X11
3927 if (f->display.x->left_pos < 0)
3928 f->display.x->left_pos
3929 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
3930
3931 if (f->display.x->top_pos < 0)
3932 f->display.x->top_pos
3933 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
3934 #else /* ! defined (HAVE_X11) */
3935 WINDOWINFO_TYPE parentinfo;
3936
3937 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
3938
3939 if (f->display.x->left_pos < 0)
3940 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
3941 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
3942
3943 if (f->display.x->top_pos < 0)
3944 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
3945 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
3946 #endif /* ! defined (HAVE_X11) */
3947 }
3948
3949 x_set_offset (f, xoff, yoff)
3950 struct frame *f;
3951 register int xoff, yoff;
3952 {
3953 f->display.x->top_pos = yoff;
3954 f->display.x->left_pos = xoff;
3955 x_calc_absolute_position (f);
3956
3957 BLOCK_INPUT;
3958 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
3959 f->display.x->left_pos, f->display.x->top_pos);
3960 #ifdef HAVE_X11
3961 x_wm_set_size_hint (f, 0);
3962 #endif /* ! defined (HAVE_X11) */
3963 UNBLOCK_INPUT;
3964 }
3965
3966 /* Call this to change the size of frame F's x-window. */
3967
3968 x_set_window_size (f, cols, rows)
3969 struct frame *f;
3970 int cols, rows;
3971 {
3972 int pixelwidth, pixelheight;
3973 int mask;
3974
3975 BLOCK_INPUT;
3976
3977 check_frame_size (f, &rows, &cols);
3978 f->display.x->vertical_scroll_bar_extra =
3979 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3980 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
3981 : 0);
3982 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3983 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3984
3985 #ifdef HAVE_X11
3986 x_wm_set_size_hint (f, 0);
3987 #endif /* ! defined (HAVE_X11) */
3988 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
3989
3990 /* Now, strictly speaking, we can't be sure that this is accurate,
3991 but the window manager will get around to dealing with the size
3992 change request eventually, and we'll hear how it went when the
3993 ConfigureNotify event gets here.
3994
3995 We could just not bother storing any of this information here,
3996 and let the ConfigureNotify event set everything up, but that
3997 might be kind of confusing to the lisp code, since size changes
3998 wouldn't be reported in the frame parameters until some random
3999 point in the future when the ConfigureNotify event arrives. */
4000 change_frame_size (f, rows, cols, 0, 0);
4001 PIXEL_WIDTH (f) = pixelwidth;
4002 PIXEL_HEIGHT (f) = pixelheight;
4003
4004 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4005 receive in the ConfigureNotify event; if we get what we asked
4006 for, then the event won't cause the screen to become garbaged, so
4007 we have to make sure to do it here. */
4008 SET_FRAME_GARBAGED (f);
4009
4010 XFlushQueue ();
4011 UNBLOCK_INPUT;
4012 }
4013
4014 #ifndef HAVE_X11
4015 x_set_resize_hint (f)
4016 struct frame *f;
4017 {
4018 XSetResizeHint (FRAME_X_WINDOW (f),
4019 2 * f->display.x->internal_border_width,
4020 2 * f->display.x->internal_border_width,
4021 FONT_WIDTH (f->display.x->font),
4022 FONT_HEIGHT (f->display.x->font));
4023 }
4024 #endif /* HAVE_X11 */
4025 \f
4026 /* Mouse warping, focus shifting, raising and lowering. */
4027
4028 x_set_mouse_position (f, x, y)
4029 struct frame *f;
4030 int x, y;
4031 {
4032 int pix_x, pix_y;
4033
4034 x_raise_frame (f);
4035
4036 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4037 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4038
4039 if (pix_x < 0) pix_x = 0;
4040 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4041
4042 if (pix_y < 0) pix_y = 0;
4043 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4044
4045 BLOCK_INPUT;
4046
4047 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4048 UNBLOCK_INPUT;
4049 }
4050
4051 #ifdef HAVE_X11
4052 x_focus_on_frame (f)
4053 struct frame *f;
4054 {
4055 x_raise_frame (f);
4056 #if 0
4057 /* I don't think that the ICCCM allows programs to do things like this
4058 without the interaction of the window manager. Whatever you end up
4059 doing with this code, do it to x_unfocus_frame too. */
4060 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4061 RevertToPointerRoot, CurrentTime);
4062 #endif /* ! 0 */
4063 }
4064
4065 x_unfocus_frame (f)
4066 struct frame *f;
4067 {
4068 #if 0
4069 /* Look at the remarks in x_focus_on_frame. */
4070 if (x_focus_frame == f)
4071 XSetInputFocus (x_current_display, PointerRoot,
4072 RevertToPointerRoot, CurrentTime);
4073 #endif /* ! 0 */
4074 }
4075
4076 #endif /* ! defined (HAVE_X11) */
4077
4078 /* Raise frame F. */
4079
4080 x_raise_frame (f)
4081 struct frame *f;
4082 {
4083 if (f->async_visible)
4084 {
4085 BLOCK_INPUT;
4086 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4087 XFlushQueue ();
4088 UNBLOCK_INPUT;
4089 }
4090 }
4091
4092 /* Lower frame F. */
4093
4094 x_lower_frame (f)
4095 struct frame *f;
4096 {
4097 if (f->async_visible)
4098 {
4099 BLOCK_INPUT;
4100 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4101 XFlushQueue ();
4102 UNBLOCK_INPUT;
4103 }
4104 }
4105
4106 static void
4107 XTframe_raise_lower (f, raise)
4108 FRAME_PTR f;
4109 int raise;
4110 {
4111 if (raise)
4112 x_raise_frame (f);
4113 else
4114 x_lower_frame (f);
4115 }
4116
4117
4118 /* Change from withdrawn state to mapped state. */
4119
4120 x_make_frame_visible (f)
4121 struct frame *f;
4122 {
4123 int mask;
4124
4125 BLOCK_INPUT;
4126
4127 if (! FRAME_VISIBLE_P (f))
4128 {
4129 #ifdef HAVE_X11
4130 if (! EQ (Vx_no_window_manager, Qt))
4131 x_wm_set_window_state (f, NormalState);
4132
4133 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4134 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4135 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4136 #else /* ! defined (HAVE_X11) */
4137 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4138 if (f->display.x->icon_desc != 0)
4139 XUnmapWindow (f->display.x->icon_desc);
4140
4141 /* Handled by the MapNotify event for X11 */
4142 f->async_visible = 1;
4143 f->async_iconified = 0;
4144
4145 /* NOTE: this may cause problems for the first frame. */
4146 XTcursor_to (0, 0);
4147 #endif /* ! defined (HAVE_X11) */
4148 }
4149
4150 XFlushQueue ();
4151
4152 UNBLOCK_INPUT;
4153 }
4154
4155 /* Change from mapped state to withdrawn state. */
4156
4157 x_make_frame_invisible (f)
4158 struct frame *f;
4159 {
4160 int mask;
4161
4162 if (! f->async_visible)
4163 return;
4164
4165 BLOCK_INPUT;
4166
4167 #ifdef HAVE_X11R4
4168
4169 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4170 DefaultScreen (x_current_display)))
4171 {
4172 UNBLOCK_INPUT_RESIGNAL;
4173 error ("can't notify window manager of window withdrawl");
4174 }
4175
4176 #else /* ! defined (HAVE_X11R4) */
4177 #ifdef HAVE_X11
4178
4179 /* Tell the window manager what we're going to do. */
4180 if (! EQ (Vx_no_window_manager, Qt))
4181 {
4182 XEvent unmap;
4183
4184 unmap.xunmap.type = UnmapNotify;
4185 unmap.xunmap.window = FRAME_X_WINDOW (f);
4186 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4187 unmap.xunmap.from_configure = False;
4188 if (! XSendEvent (x_current_display,
4189 DefaultRootWindow (x_current_display),
4190 False,
4191 SubstructureRedirectMask|SubstructureNotifyMask,
4192 &unmap))
4193 {
4194 UNBLOCK_INPUT_RESIGNAL;
4195 error ("can't notify window manager of withdrawal");
4196 }
4197 }
4198
4199 /* Unmap the window ourselves. Cheeky! */
4200 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4201
4202 #else /* ! defined (HAVE_X11) */
4203
4204 XUnmapWindow (FRAME_X_WINDOW (f));
4205 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4206 if (f->display.x->icon_desc != 0)
4207 XUnmapWindow (f->display.x->icon_desc);
4208
4209 #endif /* ! defined (HAVE_X11) */
4210 #endif /* ! defined (HAVE_X11R4) */
4211
4212 XFlushQueue ();
4213 UNBLOCK_INPUT;
4214 }
4215
4216 /* Change window state from mapped to iconified. */
4217
4218 x_iconify_frame (f)
4219 struct frame *f;
4220 {
4221 int mask;
4222
4223 if (f->async_iconified)
4224 return;
4225
4226 BLOCK_INPUT;
4227
4228 #ifdef HAVE_X11
4229 /* Since we don't know which revision of X we're running, we'll use both
4230 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4231
4232 /* X11R4: send a ClientMessage to the window manager using the
4233 WM_CHANGE_STATE type. */
4234 {
4235 XEvent message;
4236
4237 message.xclient.window = FRAME_X_WINDOW (f);
4238 message.xclient.type = ClientMessage;
4239 message.xclient.message_type = Xatom_wm_change_state;
4240 message.xclient.format = 32;
4241 message.xclient.data.l[0] = IconicState;
4242
4243 if (! XSendEvent (x_current_display,
4244 DefaultRootWindow (x_current_display),
4245 False,
4246 SubstructureRedirectMask | SubstructureNotifyMask,
4247 &message))
4248 {
4249 UNBLOCK_INPUT_RESIGNAL;
4250 error ("Can't notify window manager of iconification.");
4251 }
4252 }
4253
4254 /* X11R3: set the initial_state field of the window manager hints to
4255 IconicState. */
4256 x_wm_set_window_state (f, IconicState);
4257
4258 f->async_iconified = 1;
4259 #else /* ! defined (HAVE_X11) */
4260 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4261
4262 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4263 if (f->display.x->icon_desc != 0)
4264 {
4265 XMapWindow (XDISPLAY f->display.x->icon_desc);
4266 refreshicon (f);
4267 }
4268 #endif /* ! defined (HAVE_X11) */
4269
4270 XFlushQueue ();
4271 UNBLOCK_INPUT;
4272 }
4273
4274 /* Destroy the X window of frame F. */
4275
4276 x_destroy_window (f)
4277 struct frame *f;
4278 {
4279 BLOCK_INPUT;
4280
4281 if (f->display.x->icon_desc != 0)
4282 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4283 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4284 XFlushQueue ();
4285
4286 free (f->display.x);
4287 f->display.x = 0;
4288 if (f == x_focus_frame)
4289 x_focus_frame = 0;
4290 if (f == x_highlight_frame)
4291 x_highlight_frame = 0;
4292
4293 UNBLOCK_INPUT;
4294 }
4295 \f
4296 /* Manage event queues for X10. */
4297
4298 #ifndef HAVE_X11
4299
4300 /* Manage event queues.
4301
4302 This code is only used by the X10 support.
4303
4304 We cannot leave events in the X queue and get them when we are ready
4305 because X does not provide a subroutine to get only a certain kind
4306 of event but not block if there are no queued events of that kind.
4307
4308 Therefore, we must examine events as they come in and copy events
4309 of certain kinds into our private queues.
4310
4311 All ExposeRegion events are put in x_expose_queue.
4312 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4313
4314
4315 /* Write the event *P_XREP into the event queue *QUEUE.
4316 If the queue is full, do nothing, but return nonzero. */
4317
4318 int
4319 enqueue_event (p_xrep, queue)
4320 register XEvent *p_xrep;
4321 register struct event_queue *queue;
4322 {
4323 int newindex = queue->windex + 1;
4324 if (newindex == EVENT_BUFFER_SIZE)
4325 newindex = 0;
4326 if (newindex == queue->rindex)
4327 return -1;
4328 queue->xrep[queue->windex] = *p_xrep;
4329 queue->windex = newindex;
4330 return 0;
4331 }
4332
4333 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4334 If *QUEUE is empty, do nothing and return 0. */
4335
4336 int
4337 dequeue_event (p_xrep, queue)
4338 register XEvent *p_xrep;
4339 register struct event_queue *queue;
4340 {
4341 if (queue->windex == queue->rindex)
4342 return 0;
4343 *p_xrep = queue->xrep[queue->rindex++];
4344 if (queue->rindex == EVENT_BUFFER_SIZE)
4345 queue->rindex = 0;
4346 return 1;
4347 }
4348
4349 /* Return the number of events buffered in *QUEUE. */
4350
4351 int
4352 queue_event_count (queue)
4353 register struct event_queue *queue;
4354 {
4355 int tem = queue->windex - queue->rindex;
4356 if (tem >= 0)
4357 return tem;
4358 return EVENT_BUFFER_SIZE + tem;
4359 }
4360
4361 /* Return nonzero if mouse input is pending. */
4362
4363 int
4364 mouse_event_pending_p ()
4365 {
4366 return queue_event_count (&x_mouse_queue);
4367 }
4368 #endif /* HAVE_X11 */
4369 \f
4370 /* Setting window manager hints. */
4371
4372 #ifdef HAVE_X11
4373
4374 x_wm_set_size_hint (f, prompting)
4375 struct frame *f;
4376 long prompting;
4377 {
4378 XSizeHints size_hints;
4379 Window window = FRAME_X_WINDOW (f);
4380
4381 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
4382
4383 flexlines = f->height;
4384
4385 size_hints.x = f->display.x->left_pos;
4386 size_hints.y = f->display.x->top_pos;
4387 size_hints.height = PIXEL_HEIGHT (f);
4388 size_hints.width = PIXEL_WIDTH (f);
4389 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4390 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4391 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4392 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4393
4394 {
4395 int base_width, base_height;
4396
4397 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4398 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4399
4400 {
4401 int min_rows = 0, min_cols = 0;
4402 check_frame_size (f, &min_rows, &min_cols);
4403
4404 /* The window manager uses the base width hints to calculate the
4405 current number of rows and columns in the frame while
4406 resizing; min_width and min_height aren't useful for this
4407 purpose, since they might not give the dimensions for a
4408 zero-row, zero-column frame.
4409
4410 We use the base_width and base_height members if we have
4411 them; otherwise, we set the min_width and min_height members
4412 to the size for a zero x zero frame. */
4413
4414 #ifdef HAVE_X11R4
4415 size_hints.flags |= PBaseSize;
4416 size_hints.base_width = base_width;
4417 size_hints.base_height = base_height;
4418 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4419 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4420 #else
4421 size_hints.min_width = base_width;
4422 size_hints.min_height = base_height;
4423 #endif
4424 }
4425
4426 }
4427
4428 if (prompting)
4429 size_hints.flags |= prompting;
4430 else
4431 {
4432 XSizeHints hints; /* Sometimes I hate X Windows... */
4433
4434 XGetNormalHints (x_current_display, window, &hints);
4435 if (hints.flags & PSize)
4436 size_hints.flags |= PSize;
4437 if (hints.flags & PPosition)
4438 size_hints.flags |= PPosition;
4439 if (hints.flags & USPosition)
4440 size_hints.flags |= USPosition;
4441 if (hints.flags & USSize)
4442 size_hints.flags |= USSize;
4443 }
4444
4445 #ifdef HAVE_X11R4
4446 XSetWMNormalHints (x_current_display, window, &size_hints);
4447 #else
4448 XSetNormalHints (x_current_display, window, &size_hints);
4449 #endif
4450 }
4451
4452 /* Used for IconicState or NormalState */
4453 x_wm_set_window_state (f, state)
4454 struct frame *f;
4455 int state;
4456 {
4457 Window window = FRAME_X_WINDOW (f);
4458
4459 f->display.x->wm_hints.flags |= StateHint;
4460 f->display.x->wm_hints.initial_state = state;
4461
4462 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4463 }
4464
4465 x_wm_set_icon_pixmap (f, icon_pixmap)
4466 struct frame *f;
4467 Pixmap icon_pixmap;
4468 {
4469 Window window = FRAME_X_WINDOW (f);
4470
4471 if (icon_pixmap)
4472 {
4473 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4474 f->display.x->wm_hints.flags |= IconPixmapHint;
4475 }
4476 else
4477 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4478
4479 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4480 }
4481
4482 x_wm_set_icon_position (f, icon_x, icon_y)
4483 struct frame *f;
4484 int icon_x, icon_y;
4485 {
4486 Window window = FRAME_X_WINDOW (f);
4487
4488 f->display.x->wm_hints.flags |= IconPositionHint;
4489 f->display.x->wm_hints.icon_x = icon_x;
4490 f->display.x->wm_hints.icon_y = icon_y;
4491
4492 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4493 }
4494
4495 \f
4496 /* Initialization. */
4497
4498 void
4499 x_term_init (display_name)
4500 char *display_name;
4501 {
4502 Lisp_Object frame;
4503 char *defaultvalue;
4504 #ifdef F_SETOWN
4505 extern int old_fcntl_owner;
4506 #endif /* ! defined (F_SETOWN) */
4507
4508 x_focus_frame = x_highlight_frame = 0;
4509
4510 x_current_display = XOpenDisplay (display_name);
4511 if (x_current_display == 0)
4512 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4513 display_name);
4514
4515 #ifdef HAVE_X11
4516 {
4517 int hostname_size = 256;
4518
4519 hostname = (char *) xmalloc (hostname_size);
4520
4521 #if 0
4522 XSetAfterFunction (x_current_display, x_trace_wire);
4523 #endif /* ! 0 */
4524
4525 /* Try to get the host name; if the buffer is too short, try
4526 again. Apparently, the only indication gethostname gives of
4527 whether the buffer was large enough is the presence or absence
4528 of a '\0' in the string. Eech. */
4529 for (;;)
4530 {
4531 gethostname (hostname, hostname_size - 1);
4532 hostname[hostname_size - 1] = '\0';
4533
4534 /* Was the buffer large enough for gethostname to store the '\0'? */
4535 if (strlen (hostname) < hostname_size - 1)
4536 break;
4537
4538 hostname_size <<= 1;
4539 hostname = (char *) xrealloc (hostname, hostname_size);
4540 }
4541 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4542 + strlen (hostname)
4543 + 2);
4544 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4545 }
4546
4547 /* Figure out which modifier bits mean what. */
4548 x_find_modifier_meanings ();
4549
4550 /* Get the scroll bar cursor. */
4551 x_vertical_scroll_bar_cursor
4552 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4553
4554 #if 0
4555 /* Watch for PropertyNotify events on the root window; we use them
4556 to figure out when to invalidate our cache of the cut buffers. */
4557 x_watch_cut_buffer_cache ();
4558 #endif
4559
4560 dup2 (ConnectionNumber (x_current_display), 0);
4561
4562 #ifndef SYSV_STREAMS
4563 /* Streams somehow keeps track of which descriptor number
4564 is being used to talk to X. So it is not safe to substitute
4565 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4566 close (ConnectionNumber (x_current_display));
4567 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4568 * check the def of the macro;
4569 * it is a genuine lvalue */
4570 #endif /* SYSV_STREAMS */
4571
4572 #endif /* ! defined (HAVE_X11) */
4573
4574 #ifdef F_SETOWN
4575 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4576 #ifdef F_SETOWN_SOCK_NEG
4577 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4578 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4579 fcntl (0, F_SETOWN, getpid ());
4580 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4581 #endif /* ! defined (F_SETOWN) */
4582
4583 #ifdef SIGIO
4584 init_sigio ();
4585 #endif /* ! defined (SIGIO) */
4586
4587 /* Must use interrupt input because we cannot otherwise
4588 arrange for C-g to be noticed immediately.
4589 We cannot connect it to SIGINT. */
4590 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4591
4592 expose_all_windows = 0;
4593
4594 clear_frame_hook = XTclear_frame;
4595 clear_end_of_line_hook = XTclear_end_of_line;
4596 ins_del_lines_hook = XTins_del_lines;
4597 change_line_highlight_hook = XTchange_line_highlight;
4598 insert_glyphs_hook = XTinsert_glyphs;
4599 write_glyphs_hook = XTwrite_glyphs;
4600 delete_glyphs_hook = XTdelete_glyphs;
4601 ring_bell_hook = XTring_bell;
4602 reset_terminal_modes_hook = XTreset_terminal_modes;
4603 set_terminal_modes_hook = XTset_terminal_modes;
4604 update_begin_hook = XTupdate_begin;
4605 update_end_hook = XTupdate_end;
4606 set_terminal_window_hook = XTset_terminal_window;
4607 read_socket_hook = XTread_socket;
4608 cursor_to_hook = XTcursor_to;
4609 reassert_line_highlight_hook = XTreassert_line_highlight;
4610 mouse_position_hook = XTmouse_position;
4611 frame_rehighlight_hook = XTframe_rehighlight;
4612 frame_raise_lower_hook = XTframe_raise_lower;
4613 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4614 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4615 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4616 judge_scroll_bars_hook = XTjudge_scroll_bars;
4617
4618 scroll_region_ok = 1; /* we'll scroll partial frames */
4619 char_ins_del_ok = 0; /* just as fast to write the line */
4620 line_ins_del_ok = 1; /* we'll just blt 'em */
4621 fast_clear_end_of_line = 1; /* X does this well */
4622 memory_below_frame = 0; /* we don't remember what scrolls
4623 off the bottom */
4624 baud_rate = 19200;
4625
4626 /* Note that there is no real way portable across R3/R4 to get the
4627 original error handler. */
4628 XHandleError (x_error_quitter);
4629 XHandleIOError (x_io_error_quitter);
4630
4631 /* Disable Window Change signals; they are handled by X events. */
4632 #ifdef SIGWINCH
4633 signal (SIGWINCH, SIG_DFL);
4634 #endif /* ! defined (SIGWINCH) */
4635
4636 signal (SIGPIPE, x_connection_closed);
4637 }
4638
4639 void
4640 syms_of_xterm ()
4641 {
4642 staticpro (&last_mouse_scroll_bar);
4643 }
4644 #endif /* ! defined (HAVE_X11) */
4645 #endif /* ! defined (HAVE_X_WINDOWS) */