1 /* Implementation of Win32 GUI terminal
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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)
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.
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. */
20 /* Added by Kevin Gallo */
26 #include "blockinput.h"
39 #include "dispextern.h"
40 #include "termhooks.h"
48 #include "intervals.h"
50 extern void free_frame_menubar ();
52 extern Lisp_Object Vwindow_system
;
54 #define x_any_window_to_frame x_window_to_frame
55 #define x_top_window_to_frame x_window_to_frame
58 /* This is display since win32 does not support multiple ones. */
59 struct win32_display_info one_win32_display_info
;
61 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
62 one for each element of win32_display_list and in the same order.
63 NAME is the name of the frame.
64 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
65 Lisp_Object win32_display_name_list
;
67 /* Frame being updated by update_frame. This is declared in term.c.
68 This is set by update_begin and looked at by all the
69 win32 functions. It is zero while not inside an update.
70 In that case, the win32 functions assume that `selected_frame'
71 is the frame to apply to. */
72 extern struct frame
*updating_frame
;
74 /* This is a frame waiting to be autoraised, within w32_read_socket. */
75 struct frame
*pending_autoraise_frame
;
77 /* During an update, maximum vpos for ins/del line operations to affect. */
81 /* During an update, nonzero if chars output now should be highlighted. */
85 /* Nominal cursor position -- where to draw output.
86 During an update, these are different from the cursor-box position. */
91 DWORD dwWinThreadId
= 0;
92 HANDLE hWinThread
= NULL
;
93 DWORD dwMainThreadId
= 0;
94 HANDLE hMainThread
= NULL
;
98 /* Where the mouse was last time we reported a mouse event. */
99 static FRAME_PTR last_mouse_frame
;
100 static RECT last_mouse_glyph
;
102 Lisp_Object Vwin32_num_mouse_buttons
;
104 Lisp_Object Vwin32_swap_mouse_buttons
;
106 /* The scroll bar in which the last motion event occurred.
108 If the last motion event occurred in a scroll bar, we set this
109 so win32_mouse_position can know whether to report a scroll bar motion or
112 If the last motion event didn't occur in a scroll bar, we set this
113 to Qnil, to tell win32_mouse_position to return an ordinary motion event. */
114 Lisp_Object last_mouse_scroll_bar
;
115 int last_mouse_scroll_bar_pos
;
117 /* This is a hack. We would really prefer that win32_mouse_position would
118 return the time associated with the position it returns, but there
119 doesn't seem to be any way to wrest the timestamp from the server
120 along with the position query. So, we just keep track of the time
121 of the last movement we received, and return that in hopes that
122 it's somewhat accurate. */
123 Time last_mouse_movement_time
;
125 /* Incremented by w32_read_socket whenever it really tries to read events. */
127 static int volatile input_signal_count
;
129 static int input_signal_count
;
132 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
134 extern Lisp_Object Qface
, Qmouse_face
;
138 /* A mask of extra modifier bits to put into every keyboard char. */
139 extern int extra_keyboard_modifiers
;
141 static Lisp_Object Qvendor_specific_keysyms
;
143 void win32_delete_display ();
145 static void redraw_previous_char ();
146 static void redraw_following_char ();
147 static unsigned int win32_get_modifiers ();
149 static int fast_find_position ();
150 static void note_mouse_highlight ();
151 static void clear_mouse_face ();
152 static void show_mouse_face ();
153 static void do_line_dance ();
155 static int win32_cursor_to ();
156 static int win32_clear_end_of_line ();
159 /* This is a function useful for recording debugging information
160 about the sequence of occurrences in this file. */
168 struct record event_record
[100];
170 int event_record_index
;
172 record_event (locus
, type
)
176 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
177 event_record_index
= 0;
179 event_record
[event_record_index
].locus
= locus
;
180 event_record
[event_record_index
].type
= type
;
181 event_record_index
++;
186 /* Return the struct win32_display_info. */
188 struct win32_display_info
*
189 win32_display_info_for_display ()
191 return (&one_win32_display_info
);
195 win32_fill_rect (f
, _hdc
, pix
, lprect
)
210 hdc
= get_frame_dc (f
);
213 hb
= CreateSolidBrush (pix
);
214 FillRect (hdc
, lprect
, hb
);
218 release_frame_dc (f
, hdc
);
222 win32_clear_window (f
)
227 GetClientRect (FRAME_WIN32_WINDOW (f
), &rect
);
228 win32_clear_rect (f
, NULL
, &rect
);
232 /* Starting and ending updates.
234 These hooks are called by update_frame at the beginning and end
235 of a frame update. We record in `updating_frame' the identity
236 of the frame being updated, so that the win32_... functions do not
237 need to take a frame as argument. Most of the win32_... functions
238 should never be called except during an update, the only exceptions
239 being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight. */
242 win32_update_begin (f
)
248 flexlines
= f
->height
;
253 /* Regenerate display palette before drawing if list of requested
254 colors has changed. */
255 if (FRAME_WIN32_DISPLAY_INFO (f
)->regen_palette
)
257 win32_regenerate_palette (f
);
258 FRAME_WIN32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
261 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
263 /* Don't do highlighting for mouse motion during the update. */
264 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
266 /* If the frame needs to be redrawn,
267 simply forget about any prior mouse highlighting. */
268 if (FRAME_GARBAGED_P (f
))
269 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
271 if (!NILP (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
273 int firstline
, lastline
, i
;
274 struct window
*w
= XWINDOW (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
);
276 /* Find the first, and the last+1, lines affected by redisplay. */
277 for (firstline
= 0; firstline
< f
->height
; firstline
++)
278 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
281 lastline
= f
->height
;
282 for (i
= f
->height
- 1; i
>= 0; i
--)
284 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
290 /* Can we tell that this update does not affect the window
291 where the mouse highlight is? If so, no need to turn off.
292 Likewise, don't do anything if the frame is garbaged;
293 in that case, the FRAME_CURRENT_GLYPHS that we would use
294 are all wrong, and we will redisplay that line anyway. */
295 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
296 || lastline
< XFASTINT (w
->top
)))
297 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
311 x_display_cursor (f
, 1);
313 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
314 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
319 /* This is called after a redisplay on frame F. */
322 win32_frame_up_to_date (f
)
325 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
326 || f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
328 note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
329 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
330 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
331 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
335 /* External interface to control of standout mode.
336 Call this when about to modify line at position VPOS
337 and not change whether it is highlighted. */
339 win32_reassert_line_highlight (new, vpos
)
345 /* Call this when about to modify line at position VPOS
346 and change whether it is highlighted. */
349 win32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
350 int new_highlight
, vpos
, first_unused_hpos
;
352 highlight
= new_highlight
;
353 win32_cursor_to (vpos
, 0);
354 win32_clear_end_of_line (updating_frame
->width
);
357 /* This is used when starting Emacs and when restarting after suspend.
358 When starting Emacs, no window is mapped. And nothing must be done
359 to Emacs's own window if it is suspended (though that rarely happens). */
362 win32_set_terminal_modes ()
366 /* This is called when exiting or suspending Emacs.
367 Exiting will make the Win32 windows go away, and suspending
368 requires no action. */
371 win32_reset_terminal_modes ()
375 /* Set the nominal cursor position of the frame.
376 This is where display update commands will take effect.
377 This does not affect the place where the cursor-box is displayed. */
380 win32_cursor_to (row
, col
)
381 register int row
, col
;
388 if (updating_frame
== 0)
391 x_display_cursor (selected_frame
, 1);
396 /* Display a sequence of N glyphs found at GP.
397 WINDOW is the window to output to. LEFT and TOP are starting coords.
398 HL is 1 if this text is highlighted, 2 if the cursor is on it,
399 3 if should appear in its mouse-face.
400 JUST_FOREGROUND if 1 means draw only the foreground;
401 don't alter the background.
403 FONT is the default font to use (for glyphs whose font-code is 0).
405 Since the display generation code is responsible for calling
406 compute_char_face and compute_glyph_face on everything it puts in
407 the display structure, we can assume that the face code on each
408 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
409 to which we can actually apply intern_face.
410 Call this function with input blocked. */
413 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
416 register GLYPH
*gp
; /* Points to first GLYPH. */
417 register int n
; /* Number of glyphs to display. */
421 /* Holds characters to be displayed. */
422 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
423 register char *cp
; /* Steps through buf[]. */
424 register int tlen
= GLYPH_TABLE_LENGTH
;
425 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
426 Window window
= FRAME_WIN32_WINDOW (f
);
427 int orig_left
= left
;
430 hdc
= get_frame_dc (f
);
434 /* Get the face-code of the next GLYPH. */
438 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
439 cf
= FAST_GLYPH_FACE (g
);
441 /* Find the run of consecutive glyphs with the same face-code.
442 Extract their character codes into BUF. */
447 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
448 if (FAST_GLYPH_FACE (g
) != cf
)
451 *cp
++ = FAST_GLYPH_CHAR (g
);
456 /* LEN gets the length of the run. */
459 /* Now output this run of chars, with the font and pixel values
460 determined by the face code CF. */
462 struct face
*face
= FRAME_DEFAULT_FACE (f
);
463 XFontStruct
*font
= FACE_FONT (face
);
468 /* HL = 3 means use a mouse face previously chosen. */
470 cf
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
;
472 /* First look at the face of the text itself. */
475 /* It's possible for the display table to specify
476 a face code that is out of range. Use 0 in that case. */
477 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
478 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
482 face
= FRAME_MODE_LINE_FACE (f
);
484 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
485 font
= FACE_FONT (face
);
486 if (FACE_STIPPLE (face
))
490 /* Then comes the distinction between modeline and normal text. */
495 face
= FRAME_MODE_LINE_FACE (f
);
496 font
= FACE_FONT (face
);
497 if (FACE_STIPPLE (face
))
501 fg
= face
->foreground
;
502 bg
= face
->background
;
504 /* Now override that if the cursor's on this character. */
507 /* The cursor overrides stippling. */
511 || face
->font
== (XFontStruct
*) FACE_DEFAULT
512 || face
->font
== f
->output_data
.win32
->font
)
513 && face
->background
== f
->output_data
.win32
->background_pixel
514 && face
->foreground
== f
->output_data
.win32
->foreground_pixel
)
516 bg
= f
->output_data
.win32
->cursor_pixel
;
517 fg
= face
->background
;
519 /* Cursor on non-default face: must merge. */
522 bg
= f
->output_data
.win32
->cursor_pixel
;
523 fg
= face
->background
;
524 /* If the glyph would be invisible,
525 try a different foreground. */
527 fg
= face
->foreground
;
529 fg
= f
->output_data
.win32
->cursor_foreground_pixel
;
531 fg
= face
->foreground
;
532 /* Make sure the cursor is distinct from text in this face. */
533 if (bg
== face
->background
534 && fg
== face
->foreground
)
536 bg
= face
->foreground
;
537 fg
= face
->background
;
542 if (font
== (XFontStruct
*) FACE_DEFAULT
)
543 font
= f
->output_data
.win32
->font
;
545 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
547 SetTextColor (hdc
, fg
);
548 SetBkColor (hdc
, bg
);
550 SelectObject (hdc
, font
->hfont
);
552 TextOut (hdc
, left
, top
, buf
, len
);
554 if (!just_foreground
)
556 /* Clear the rest of the line's height. */
557 if (f
->output_data
.win32
->line_height
!= FONT_HEIGHT (font
))
558 win32_fill_area (f
, hdc
, bg
,
560 top
+ FONT_HEIGHT (font
),
561 FONT_WIDTH (font
) * len
,
562 f
->output_data
.win32
->line_height
- FONT_HEIGHT (font
));
566 int underline_position
= 1;
568 if (font
->tm
.tmDescent
<= underline_position
)
569 underline_position
= font
->tm
.tmDescent
- 1;
572 win32_fill_area (f
, hdc
, fg
,
575 + underline_position
),
576 len
* FONT_WIDTH (font
), 1);
579 left
+= len
* FONT_WIDTH (font
);
583 release_frame_dc (f
, hdc
);
587 /* Output some text at the nominal frame cursor position.
588 Advance the cursor over the text.
589 Output LEN glyphs at START.
591 `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
592 controls the pixel values used for foreground and background. */
595 win32_write_glyphs (start
, len
)
596 register GLYPH
*start
;
599 register int temp_length
;
609 /* If not within an update,
610 output at the frame's visible cursor. */
611 curs_x
= f
->cursor_x
;
612 curs_y
= f
->cursor_y
;
616 CHAR_TO_PIXEL_COL (f
, curs_x
),
617 CHAR_TO_PIXEL_ROW (f
, curs_y
),
618 start
, len
, highlight
, 0);
620 /* If we drew on top of the cursor, note that it is turned off. */
621 if (curs_y
== f
->phys_cursor_y
622 && curs_x
<= f
->phys_cursor_x
623 && curs_x
+ len
> f
->phys_cursor_x
)
624 f
->phys_cursor_x
= -1;
626 if (updating_frame
== 0)
629 x_display_cursor (f
, 1);
638 /* Clear to the end of the line.
639 Erase the current text line from the nominal cursor position (inclusive)
640 to column FIRST_UNUSED (exclusive). The idea is that everything
641 from FIRST_UNUSED onward is already erased. */
644 win32_clear_end_of_line (first_unused
)
645 register int first_unused
;
647 struct frame
*f
= updating_frame
;
652 if (curs_y
< 0 || curs_y
>= f
->height
)
654 if (first_unused
<= 0)
657 if (first_unused
>= f
->width
)
658 first_unused
= f
->width
;
664 /* Notice if the cursor will be cleared by this operation. */
665 if (curs_y
== f
->phys_cursor_y
666 && curs_x
<= f
->phys_cursor_x
667 && f
->phys_cursor_x
< first_unused
)
668 f
->phys_cursor_x
= -1;
670 win32_clear_area (f
, NULL
,
671 CHAR_TO_PIXEL_COL (f
, curs_x
),
672 CHAR_TO_PIXEL_ROW (f
, curs_y
),
673 FONT_WIDTH (f
->output_data
.win32
->font
) * (first_unused
- curs_x
),
674 f
->output_data
.win32
->line_height
);
682 struct frame
*f
= updating_frame
;
687 f
->phys_cursor_x
= -1; /* Cursor not visible. */
688 curs_x
= 0; /* Nominal cursor position is top left. */
693 win32_clear_window (f
);
695 /* We have to clear the scroll bars, too. If we have changed
696 colors or something like that, then they should be notified. */
697 x_scroll_bar_clear (f
);
702 /* Make audible bell. */
709 FlashWindow (FRAME_WIN32_WINDOW (selected_frame
), FALSE
);
718 /* Insert and delete character.
719 These are not supposed to be used because we are supposed to turn
720 off the feature of using them. */
723 win32_insert_glyphs (start
, len
)
724 register char *start
;
731 win32_delete_glyphs (n
)
737 /* Specify how many text lines, from the top of the window,
738 should be affected by insert-lines and delete-lines operations.
739 This, and those operations, are used only within an update
740 that is bounded by calls to win32_update_begin and win32_update_end. */
743 win32_set_terminal_window (n
)
746 if (updating_frame
== 0)
749 if ((n
<= 0) || (n
> updating_frame
->height
))
750 flexlines
= updating_frame
->height
;
755 /* These variables need not be per frame
756 because redisplay is done on a frame-by-frame basis
757 and the line dance for one frame is finished before
758 anything is done for another frame. */
760 /* Array of line numbers from cached insert/delete operations.
761 line_dance[i] is the old position of the line that we want
762 to move to line i, or -1 if we want a blank line there. */
763 static int *line_dance
;
765 /* Allocated length of that array. */
766 static int line_dance_len
;
768 /* Flag indicating whether we've done any work. */
769 static int line_dance_in_progress
;
771 /* Perform an insert-lines or delete-lines operation,
772 inserting N lines or deleting -N lines at vertical position VPOS. */
773 win32_ins_del_lines (vpos
, n
)
776 register int fence
, i
;
778 if (vpos
>= flexlines
)
781 if (!line_dance_in_progress
)
783 int ht
= updating_frame
->height
;
784 if (ht
> line_dance_len
)
786 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
789 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
790 line_dance_in_progress
= 1;
794 if (n
> flexlines
- vpos
)
795 n
= flexlines
- vpos
;
797 for (i
= flexlines
; --i
>= fence
;)
798 line_dance
[i
] = line_dance
[i
-n
];
799 for (i
= fence
; --i
>= vpos
;)
805 if (n
> flexlines
- vpos
)
806 n
= flexlines
- vpos
;
807 fence
= flexlines
- n
;
808 for (i
= vpos
; i
< fence
; ++i
)
809 line_dance
[i
] = line_dance
[i
+ n
];
810 for (i
= fence
; i
< flexlines
; ++i
)
815 /* Here's where we actually move the pixels around.
816 Must be called with input blocked. */
820 register int i
, j
, distance
;
821 register struct frame
*f
;
826 /* Must check this flag first. If it's not set, then not only is the
827 array uninitialized, but we might not even have a frame. */
828 if (!line_dance_in_progress
)
836 intborder
= f
->output_data
.win32
->internal_border_width
;
838 x_display_cursor (updating_frame
, 0);
840 hdc
= get_frame_dc (f
);
842 for (i
= 0; i
< ht
; ++i
)
843 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
845 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
846 && line_dance
[j
]-j
== distance
); ++j
);
847 /* Copy [i,j) upward from [i+distance, j+distance) */
849 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
850 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
851 (j
-i
) * f
->output_data
.win32
->line_height
,
853 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
858 for (i
= ht
; --i
>=0; )
859 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
861 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
862 && line_dance
[j
]-j
== distance
););
863 /* Copy (j, i] downward from (j+distance, i+distance] */
865 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
866 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
867 (i
-j
) * f
->output_data
.win32
->line_height
,
869 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
874 release_frame_dc (f
, hdc
);
876 for (i
= 0; i
< ht
; ++i
)
877 if (line_dance
[i
] == -1)
879 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
881 win32_clear_area (f
, NULL
,
883 CHAR_TO_PIXEL_ROW (f
, i
),
884 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
885 (j
-i
) * f
->output_data
.win32
->line_height
);
888 line_dance_in_progress
= 0;
891 /* Support routines for exposure events. */
892 static void clear_cursor ();
894 /* Output into a rectangle of a window (for frame F)
895 the characters in f->phys_lines that overlap that rectangle.
896 TOP and LEFT are the position of the upper left corner of the rectangle.
897 ROWS and COLS are the size of the rectangle.
898 Call this function with input blocked. */
901 dumprectangle (f
, left
, top
, cols
, rows
)
903 register int left
, top
, cols
, rows
;
905 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
906 int cursor_cleared
= 0;
910 if (FRAME_GARBAGED_P (f
))
913 /* Express rectangle as four edges, instead of position-and-size. */
917 /* Convert rectangle edges in pixels to edges in chars.
918 Round down for left and top, up for right and bottom. */
919 top
= PIXEL_TO_CHAR_ROW (f
, top
);
920 left
= PIXEL_TO_CHAR_COL (f
, left
);
921 bottom
+= (f
->output_data
.win32
->line_height
- 1);
922 right
+= (FONT_WIDTH (f
->output_data
.win32
->font
) - 1);
923 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
924 right
= PIXEL_TO_CHAR_COL (f
, right
);
926 /* Clip the rectangle to what can be visible. */
931 if (right
> f
->width
)
933 if (bottom
> f
->height
)
936 /* Get size in chars of the rectangle. */
940 /* If rectangle has zero area, return. */
941 if (rows
<= 0) return;
942 if (cols
<= 0) return;
944 /* Turn off the cursor if it is in the rectangle.
945 We will turn it back on afterward. */
946 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
947 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
953 /* Display the text in the rectangle, one text line at a time. */
955 for (y
= top
; y
< bottom
; y
++)
957 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
959 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
963 CHAR_TO_PIXEL_COL (f
, left
),
964 CHAR_TO_PIXEL_ROW (f
, y
),
965 line
, min (cols
, active_frame
->used
[y
] - left
),
966 active_frame
->highlight
[y
], 0);
969 /* Turn the cursor on if we turned it off. */
972 x_display_cursor (f
, 1);
979 x_display_cursor (f
, 1);
983 frame_unhighlight (f
)
986 x_display_cursor (f
, 1);
989 static void win32_frame_rehighlight ();
990 static void x_frame_rehighlight ();
992 /* The focus has changed. Update the frames as necessary to reflect
993 the new situation. Note that we can't change the selected frame
994 here, because the Lisp code we are interrupting might become confused.
995 Each event gets marked with the frame in which it occurred, so the
996 Lisp code can tell when the switch took place by examining the events. */
999 x_new_focus_frame (dpyinfo
, frame
)
1000 struct win32_display_info
*dpyinfo
;
1001 struct frame
*frame
;
1003 struct frame
*old_focus
= dpyinfo
->win32_focus_frame
;
1004 int events_enqueued
= 0;
1006 if (frame
!= dpyinfo
->win32_focus_frame
)
1008 /* Set this before calling other routines, so that they see
1009 the correct value of win32_focus_frame. */
1010 dpyinfo
->win32_focus_frame
= frame
;
1012 if (old_focus
&& old_focus
->auto_lower
)
1013 x_lower_frame (old_focus
);
1015 if (dpyinfo
->win32_focus_frame
&& dpyinfo
->win32_focus_frame
->auto_raise
)
1016 pending_autoraise_frame
= dpyinfo
->win32_focus_frame
;
1018 pending_autoraise_frame
= 0;
1021 x_frame_rehighlight (dpyinfo
);
1024 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1027 x_mouse_leave (dpyinfo
)
1028 struct win32_display_info
*dpyinfo
;
1030 x_new_focus_frame (dpyinfo
, dpyinfo
->win32_focus_event_frame
);
1033 /* The focus has changed, or we have redirected a frame's focus to
1034 another frame (this happens when a frame uses a surrogate
1035 minibuffer frame). Shift the highlight as appropriate.
1037 The FRAME argument doesn't necessarily have anything to do with which
1038 frame is being highlighted or unhighlighted; we only use it to find
1039 the appropriate display info. */
1041 win32_frame_rehighlight (frame
)
1042 struct frame
*frame
;
1044 x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame
));
1048 x_frame_rehighlight (dpyinfo
)
1049 struct win32_display_info
*dpyinfo
;
1051 struct frame
*old_highlight
= dpyinfo
->win32_highlight_frame
;
1053 if (dpyinfo
->win32_focus_frame
)
1055 dpyinfo
->win32_highlight_frame
1056 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
)))
1057 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
))
1058 : dpyinfo
->win32_focus_frame
);
1059 if (! FRAME_LIVE_P (dpyinfo
->win32_highlight_frame
))
1061 FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
) = Qnil
;
1062 dpyinfo
->win32_highlight_frame
= dpyinfo
->win32_focus_frame
;
1066 dpyinfo
->win32_highlight_frame
= 0;
1068 if (dpyinfo
->win32_highlight_frame
!= old_highlight
)
1071 frame_unhighlight (old_highlight
);
1072 if (dpyinfo
->win32_highlight_frame
)
1073 frame_highlight (dpyinfo
->win32_highlight_frame
);
1077 /* Keyboard processing - modifier keys, etc. */
1079 /* Convert a keysym to its name. */
1082 x_get_keysym_name (keysym
)
1085 /* Make static so we can always return it */
1086 static char value
[100];
1089 GetKeyNameText(keysym
, value
, 100);
1095 /* Mouse clicks and mouse movement. Rah. */
1097 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1098 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1099 that the glyph at X, Y occupies, if BOUNDS != 0.
1100 If NOCLIP is nonzero, do not force the value into range. */
1103 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1105 register int pix_x
, pix_y
;
1106 register int *x
, *y
;
1110 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1111 if (NILP (Vwindow_system
))
1118 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1119 even for negative values. */
1121 pix_x
-= FONT_WIDTH ((f
)->output_data
.win32
->font
) - 1;
1123 pix_y
-= (f
)->output_data
.win32
->line_height
- 1;
1125 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1126 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1130 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1131 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1132 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.win32
->font
) - 1;
1133 bounds
->bottom
= bounds
->top
+ f
->output_data
.win32
->line_height
- 1;
1140 else if (pix_x
> f
->width
)
1145 else if (pix_y
> f
->height
)
1154 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1157 register int *pix_x
, *pix_y
;
1159 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1160 if (NILP (Vwindow_system
))
1167 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1168 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1172 parse_button (message
, pbutton
, pup
)
1182 case WM_LBUTTONDOWN
:
1190 case WM_MBUTTONDOWN
:
1191 if (NILP (Vwin32_swap_mouse_buttons
))
1198 if (NILP (Vwin32_swap_mouse_buttons
))
1204 case WM_RBUTTONDOWN
:
1205 if (NILP (Vwin32_swap_mouse_buttons
))
1212 if (NILP (Vwin32_swap_mouse_buttons
))
1223 if (pbutton
) *pbutton
= button
;
1229 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1231 If the event is a button press, then note that we have grabbed
1235 construct_mouse_click (result
, msg
, f
)
1236 struct input_event
*result
;
1243 parse_button (msg
->msg
.message
, &button
, &up
);
1245 /* Make the event type no_event; we'll change that when we decide
1247 result
->kind
= mouse_click
;
1248 result
->code
= button
;
1249 result
->timestamp
= msg
->msg
.time
;
1250 result
->modifiers
= (msg
->dwModifiers
1258 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1259 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1260 XSETFRAME (result
->frame_or_window
, f
);
1265 /* Function to report a mouse movement to the mainstream Emacs code.
1266 The input handler calls this.
1268 We have received a mouse movement event, which is given in *event.
1269 If the mouse is over a different glyph than it was last time, tell
1270 the mainstream emacs code by setting mouse_moved. If not, ask for
1271 another motion event, so we can check again the next time it moves. */
1274 note_mouse_movement (frame
, msg
)
1278 last_mouse_movement_time
= msg
->time
;
1280 if (msg
->hwnd
!= FRAME_WIN32_WINDOW (frame
))
1282 frame
->mouse_moved
= 1;
1283 last_mouse_scroll_bar
= Qnil
;
1285 note_mouse_highlight (frame
, -1, -1);
1288 /* Has the mouse moved off the glyph it was on at the last sighting? */
1289 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1290 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1291 || HIWORD (msg
->lParam
) < last_mouse_glyph
.left
1292 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1294 frame
->mouse_moved
= 1;
1295 last_mouse_scroll_bar
= Qnil
;
1297 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1301 /* This is used for debugging, to turn off note_mouse_highlight. */
1302 static int disable_mouse_highlight
;
1304 /* Take proper action when the mouse has moved to position X, Y on frame F
1305 as regards highlighting characters that have mouse-face properties.
1306 Also dehighlighting chars where the mouse was before.
1307 X and Y can be negative or out of range. */
1310 note_mouse_highlight (f
, x
, y
)
1314 int row
, column
, portion
;
1319 if (disable_mouse_highlight
)
1322 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1323 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1324 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1326 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
)
1331 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1335 /* Find out which glyph the mouse is on. */
1336 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1337 &new_glyph
, FRAME_WIN32_DISPLAY_INFO (f
)->grabbed
);
1339 /* Which window is that in? */
1340 window
= window_from_coordinates (f
, column
, row
, &portion
);
1341 w
= XWINDOW (window
);
1343 /* If we were displaying active text in another window, clear that. */
1344 if (! EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
1345 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1347 /* Are we in a window whose display is up to date?
1348 And verify the buffer's text has not changed. */
1349 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1350 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1351 && EQ (w
->window_end_valid
, w
->buffer
)
1352 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1354 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1357 /* Find which buffer position the mouse corresponds to. */
1358 for (i
= column
; i
>= 0; i
--)
1362 /* Is it outside the displayed active region (if any)? */
1364 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1365 else if (! (EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
)
1366 && row
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1367 && row
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1368 && (row
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1369 || column
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1370 && (row
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1371 || column
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1372 || FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1374 Lisp_Object mouse_face
, overlay
, position
;
1375 Lisp_Object
*overlay_vec
;
1376 int len
, noverlays
, ignor1
;
1377 struct buffer
*obuf
;
1380 /* If we get an out-of-range value, return now; avoid an error. */
1381 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1384 /* Make the window's buffer temporarily current for
1385 overlays_at and compute_char_face. */
1386 obuf
= current_buffer
;
1387 current_buffer
= XBUFFER (w
->buffer
);
1393 /* Yes. Clear the display of the old active region, if any. */
1394 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1396 /* Is this char mouse-active? */
1397 XSETINT (position
, pos
);
1400 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1402 /* Put all the overlays we want in a vector in overlay_vec.
1403 Store the length in len. */
1404 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1406 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1408 /* Find the highest priority overlay that has a mouse-face prop. */
1410 for (i
= 0; i
< noverlays
; i
++)
1412 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1413 if (!NILP (mouse_face
))
1415 overlay
= overlay_vec
[i
];
1420 /* If no overlay applies, get a text property. */
1422 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1424 /* Handle the overlay case. */
1425 if (! NILP (overlay
))
1427 /* Find the range of text around this char that
1428 should be active. */
1429 Lisp_Object before
, after
;
1432 before
= Foverlay_start (overlay
);
1433 after
= Foverlay_end (overlay
);
1434 /* Record this as the current active region. */
1435 fast_find_position (window
, before
,
1436 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1437 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1438 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1439 = !fast_find_position (window
, after
,
1440 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1441 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1442 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1443 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1444 = compute_char_face (f
, w
, pos
, 0, 0,
1445 &ignore
, pos
+ 1, 1);
1447 /* Display it as active. */
1448 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1450 /* Handle the text property case. */
1451 else if (! NILP (mouse_face
))
1453 /* Find the range of text around this char that
1454 should be active. */
1455 Lisp_Object before
, after
, beginning
, end
;
1458 beginning
= Fmarker_position (w
->start
);
1459 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1460 - XFASTINT (w
->window_end_pos
)));
1462 = Fprevious_single_property_change (make_number (pos
+ 1),
1464 w
->buffer
, beginning
);
1466 = Fnext_single_property_change (position
, Qmouse_face
,
1468 /* Record this as the current active region. */
1469 fast_find_position (window
, before
,
1470 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1471 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1472 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1473 = !fast_find_position (window
, after
,
1474 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1475 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1476 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1477 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1478 = compute_char_face (f
, w
, pos
, 0, 0,
1479 &ignore
, pos
+ 1, 1);
1481 /* Display it as active. */
1482 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1486 current_buffer
= obuf
;
1491 /* Find the row and column of position POS in window WINDOW.
1492 Store them in *COLUMNP and *ROWP.
1493 This assumes display in WINDOW is up to date.
1494 If POS is above start of WINDOW, return coords
1495 of start of first screen line.
1496 If POS is after end of WINDOW, return coords of end of last screen line.
1498 Value is 1 if POS is in range, 0 if it was off screen. */
1501 fast_find_position (window
, pos
, columnp
, rowp
)
1504 int *columnp
, *rowp
;
1506 struct window
*w
= XWINDOW (window
);
1507 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1512 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1513 int width
= window_internal_width (w
);
1516 int maybe_next_line
= 0;
1518 /* Find the right row. */
1523 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1524 if (linestart
> pos
)
1526 /* If the position sought is the end of the buffer,
1527 don't include the blank lines at the bottom of the window. */
1528 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1530 maybe_next_line
= 1;
1537 /* Find the right column with in it. */
1538 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1540 for (i
= 0; i
< width
; i
++)
1542 if (charstarts
[left
+ i
] == pos
)
1545 *columnp
= i
+ left
;
1548 else if (charstarts
[left
+ i
] > pos
)
1550 else if (charstarts
[left
+ i
] > 0)
1554 /* If we're looking for the end of the buffer,
1555 and we didn't find it in the line we scanned,
1556 use the start of the following line. */
1557 if (maybe_next_line
)
1568 /* Display the active region described by mouse_face_*
1569 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1572 show_mouse_face (dpyinfo
, hl
)
1573 struct win32_display_info
*dpyinfo
;
1576 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1577 int width
= window_internal_width (w
);
1578 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1581 int old_curs_x
= curs_x
;
1582 int old_curs_y
= curs_y
;
1584 /* Set these variables temporarily
1585 so that if we have to turn the cursor off and on again
1586 we will put it back at the same place. */
1587 curs_x
= f
->phys_cursor_x
;
1588 curs_y
= f
->phys_cursor_y
;
1590 for (i
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1591 i
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1593 int column
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1594 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
1596 int endcolumn
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1597 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1599 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1601 /* If the cursor's in the text we are about to rewrite,
1602 turn the cursor off. */
1604 && curs_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
1605 && curs_x
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
)
1607 x_display_cursor (f
, 0);
1612 CHAR_TO_PIXEL_COL (f
, column
),
1613 CHAR_TO_PIXEL_ROW (f
, i
),
1614 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1616 /* Highlight with mouse face if hl > 0. */
1620 /* If we turned the cursor off, turn it back on. */
1622 x_display_cursor (f
, 1);
1624 curs_x
= old_curs_x
;
1625 curs_y
= old_curs_y
;
1627 /* Change the mouse cursor according to the value of HL. */
1629 SetCursor (f
->output_data
.win32
->cross_cursor
);
1631 SetCursor (f
->output_data
.win32
->text_cursor
);
1634 /* Clear out the mouse-highlighted active region.
1635 Redraw it unhighlighted first. */
1638 clear_mouse_face (dpyinfo
)
1639 struct win32_display_info
*dpyinfo
;
1641 if (! NILP (dpyinfo
->mouse_face_window
))
1642 show_mouse_face (dpyinfo
, 0);
1644 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1645 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1646 dpyinfo
->mouse_face_window
= Qnil
;
1649 struct scroll_bar
*x_window_to_scroll_bar ();
1650 static void x_scroll_bar_report_motion ();
1652 /* Return the current position of the mouse.
1653 *fp should be a frame which indicates which display to ask about.
1655 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1656 and *part to the frame, window, and scroll bar part that the mouse
1657 is over. Set *x and *y to the portion and whole of the mouse's
1658 position on the scroll bar.
1660 If the mouse movement started elsewhere, set *fp to the frame the
1661 mouse is on, *bar_window to nil, and *x and *y to the character cell
1664 Set *time to the server timestamp for the time at which the mouse
1665 was at this position.
1667 Don't store anything if we don't have a valid set of values to report.
1669 This clears the mouse_moved flag, so we can wait for the next mouse
1670 movement. This also calls XQueryPointer, which will cause the
1671 server to give us another MotionNotify when the mouse moves
1675 win32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1678 Lisp_Object
*bar_window
;
1679 enum scroll_bar_part
*part
;
1681 unsigned long *time
;
1687 if (! NILP (last_mouse_scroll_bar
))
1688 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1693 Lisp_Object frame
, tail
;
1695 /* Clear the mouse-moved flag for every frame on this display. */
1696 FOR_EACH_FRAME (tail
, frame
)
1697 XFRAME (frame
)->mouse_moved
= 0;
1699 last_mouse_scroll_bar
= Qnil
;
1703 /* Now we have a position on the root; find the innermost window
1704 containing the pointer. */
1706 if (FRAME_WIN32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1707 && FRAME_LIVE_P (last_mouse_frame
))
1709 f1
= last_mouse_frame
;
1713 /* Is win one of our frames? */
1714 f1
= x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1717 /* If not, is it one of our scroll bars? */
1720 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1724 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1728 if (f1
== 0 && insist
)
1729 f1
= selected_frame
;
1733 int ignore1
, ignore2
;
1735 ScreenToClient (FRAME_WIN32_WINDOW (f1
), &pt
);
1737 /* Ok, we found a frame. Store all the values. */
1739 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1741 FRAME_WIN32_DISPLAY_INFO (f1
)->grabbed
1749 *time
= last_mouse_movement_time
;
1757 /* Scroll bar support. */
1759 /* Given an window ID, find the struct scroll_bar which manages it.
1760 This can be called in GC, so we have to make sure to strip off mark
1763 x_window_to_scroll_bar (window_id
)
1766 Lisp_Object tail
, frame
;
1768 for (tail
= Vframe_list
;
1769 XGCTYPE (tail
) == Lisp_Cons
;
1770 tail
= XCONS (tail
)->cdr
)
1772 Lisp_Object frame
, bar
, condemned
;
1774 frame
= XCONS (tail
)->car
;
1775 /* All elements of Vframe_list should be frames. */
1776 if (! GC_FRAMEP (frame
))
1779 /* Scan this frame's scroll bar list for a scroll bar with the
1781 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1782 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1783 /* This trick allows us to search both the ordinary and
1784 condemned scroll bar lists with one loop. */
1785 ! GC_NILP (bar
) || (bar
= condemned
,
1788 bar
= XSCROLL_BAR (bar
)->next
)
1789 if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1790 return XSCROLL_BAR (bar
);
1797 my_create_scrollbar (f
, bar
)
1799 struct scroll_bar
* bar
;
1803 PostThreadMessage (dwWinThreadId
, WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1805 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
1807 return ((HWND
) msg
.wParam
);
1810 //#define ATTACH_THREADS
1813 my_show_window (HWND hwnd
, int how
)
1815 #ifndef ATTACH_THREADS
1816 SendMessage (hwnd
, WM_EMACS_SHOWWINDOW
, (WPARAM
) how
, 0);
1818 ShowWindow (hwnd
, how
);
1823 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
1824 int x
, int y
, int cx
, int cy
, int flags
)
1826 #ifndef ATTACH_THREADS
1828 pos
.hwndAfter
= hwndAfter
;
1834 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
1836 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1841 my_destroy_window (f
, hwnd
)
1845 SendMessage (FRAME_WIN32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
1849 /* Open a new window to serve as a scroll bar, and return the
1850 scroll bar vector for it. */
1851 static struct scroll_bar
*
1852 x_scroll_bar_create (window
, top
, left
, width
, height
)
1853 struct window
*window
;
1854 int top
, left
, width
, height
;
1856 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1857 struct scroll_bar
*bar
1858 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1863 XSETWINDOW (bar
->window
, window
);
1864 XSETINT (bar
->top
, top
);
1865 XSETINT (bar
->left
, left
);
1866 XSETINT (bar
->width
, width
);
1867 XSETINT (bar
->height
, height
);
1868 XSETINT (bar
->start
, 0);
1869 XSETINT (bar
->end
, 0);
1870 bar
->dragging
= Qnil
;
1872 /* Requires geometry to be set before call to create the real window */
1874 hwnd
= my_create_scrollbar (f
, bar
);
1876 SetScrollRange (hwnd
, SB_CTL
, 0, height
, FALSE
);
1877 SetScrollPos (hwnd
, SB_CTL
, 0, TRUE
);
1879 SET_SCROLL_BAR_WIN32_WINDOW (bar
, hwnd
);
1881 /* Add bar to its frame's list of scroll bars. */
1882 bar
->next
= FRAME_SCROLL_BARS (f
);
1884 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
1885 if (! NILP (bar
->next
))
1886 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
1893 /* Draw BAR's handle in the proper position.
1894 If the handle is already drawn from START to END, don't bother
1895 redrawing it, unless REBUILD is non-zero; in that case, always
1896 redraw it. (REBUILD is handy for drawing the handle after expose
1899 Normally, we want to constrain the start and end of the handle to
1900 fit inside its rectangle, but if the user is dragging the scroll bar
1901 handle, we want to let them drag it down all the way, so that the
1902 bar's top is as far down as it goes; otherwise, there's no way to
1903 move to the very end of the buffer. */
1905 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1906 struct scroll_bar
*bar
;
1910 int dragging
= ! NILP (bar
->dragging
);
1911 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1912 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1914 /* If the display is already accurate, do nothing. */
1916 && start
== XINT (bar
->start
)
1917 && end
== XINT (bar
->end
))
1922 /* Store the adjusted setting in the scroll bar. */
1923 XSETINT (bar
->start
, start
);
1924 XSETINT (bar
->end
, end
);
1926 /* If we are less than half of the page use start otherwise use end */
1928 SetScrollPos (w
, SB_CTL
, ((start
>> 1) < bar
->height
)?start
:end
, TRUE
);
1933 /* Move a scroll bar around on the screen, to accommodate changing
1934 window configurations. */
1936 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1937 struct scroll_bar
*bar
;
1938 int top
, left
, width
, height
;
1940 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1941 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1945 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
1946 SetScrollRange (w
, SB_CTL
, 0, height
, FALSE
);
1947 InvalidateRect (w
, NULL
, FALSE
);
1949 XSETINT (bar
->left
, left
);
1950 XSETINT (bar
->top
, top
);
1951 XSETINT (bar
->width
, width
);
1952 XSETINT (bar
->height
, height
);
1957 /* Destroy the window for BAR, and set its Emacs window's scroll bar
1960 x_scroll_bar_remove (bar
)
1961 struct scroll_bar
*bar
;
1963 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1967 /* Destroy the window. */
1968 my_destroy_window (f
, SCROLL_BAR_WIN32_WINDOW (bar
));
1970 /* Disassociate this scroll bar from its window. */
1971 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
1976 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1977 that we are displaying PORTION characters out of a total of WHOLE
1978 characters, starting at POSITION. If WINDOW has no scroll bar,
1981 win32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
1982 struct window
*window
;
1983 int portion
, whole
, position
;
1985 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1986 int top
= XINT (window
->top
);
1987 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
1988 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
1990 /* Where should this scroll bar be, pixelwise? */
1991 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
1992 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
1994 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
1995 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
1996 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
1997 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
1999 struct scroll_bar
*bar
;
2001 /* Does the scroll bar exist yet? */
2002 if (NILP (window
->vertical_scroll_bar
))
2003 bar
= x_scroll_bar_create (window
,
2004 pixel_top
, pixel_left
,
2005 pixel_width
, pixel_height
);
2008 /* It may just need to be moved and resized. */
2009 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2010 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2013 /* Set the scroll bar's current state, unless we're currently being
2015 if (NILP (bar
->dragging
))
2017 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2020 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2023 int start
= (int) (((double) position
* top_range
) / whole
);
2024 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2026 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2030 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2034 /* The following three hooks are used when we're doing a thorough
2035 redisplay of the frame. We don't explicitly know which scroll bars
2036 are going to be deleted, because keeping track of when windows go
2037 away is a real pain - "Can you say set-window-configuration, boys
2038 and girls?" Instead, we just assert at the beginning of redisplay
2039 that *all* scroll bars are to be removed, and then save a scroll bar
2040 from the fiery pit when we actually redisplay its window. */
2042 /* Arrange for all scroll bars on FRAME to be removed at the next call
2043 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2044 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2046 win32_condemn_scroll_bars (frame
)
2049 /* The condemned list should be empty at this point; if it's not,
2050 then the rest of Emacs isn't using the condemn/redeem/judge
2051 protocol correctly. */
2052 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2055 /* Move them all to the "condemned" list. */
2056 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2057 FRAME_SCROLL_BARS (frame
) = Qnil
;
2060 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2061 Note that WINDOW isn't necessarily condemned at all. */
2063 win32_redeem_scroll_bar (window
)
2064 struct window
*window
;
2066 struct scroll_bar
*bar
;
2068 /* We can't redeem this window's scroll bar if it doesn't have one. */
2069 if (NILP (window
->vertical_scroll_bar
))
2072 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2074 /* Unlink it from the condemned list. */
2076 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2078 if (NILP (bar
->prev
))
2080 /* If the prev pointer is nil, it must be the first in one of
2082 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2083 /* It's not condemned. Everything's fine. */
2085 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2086 window
->vertical_scroll_bar
))
2087 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2089 /* If its prev pointer is nil, it must be at the front of
2090 one or the other! */
2094 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2096 if (! NILP (bar
->next
))
2097 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2099 bar
->next
= FRAME_SCROLL_BARS (f
);
2101 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2102 if (! NILP (bar
->next
))
2103 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2107 /* Remove all scroll bars on FRAME that haven't been saved since the
2108 last call to `*condemn_scroll_bars_hook'. */
2110 win32_judge_scroll_bars (f
)
2113 Lisp_Object bar
, next
;
2115 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2117 /* Clear out the condemned list now so we won't try to process any
2118 more events on the hapless scroll bars. */
2119 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2121 for (; ! NILP (bar
); bar
= next
)
2123 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2125 x_scroll_bar_remove (b
);
2128 b
->next
= b
->prev
= Qnil
;
2131 /* Now there should be no references to the condemned scroll bars,
2132 and they should get garbage-collected. */
2135 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2136 is set to something other than no_event, it is enqueued.
2138 This may be called from a signal handler, so we have to ignore GC
2141 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2142 struct scroll_bar
*bar
;
2144 struct input_event
*emacs_event
;
2146 if (! GC_WINDOWP (bar
->window
))
2149 emacs_event
->kind
= win32_scroll_bar_click
;
2150 emacs_event
->code
= 0;
2151 /* not really meaningful to distinguish up/down */
2152 emacs_event
->modifiers
= msg
->dwModifiers
;
2153 emacs_event
->frame_or_window
= bar
->window
;
2154 emacs_event
->timestamp
= msg
->msg
.time
;
2158 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2160 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2161 int y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2163 switch (LOWORD (msg
->msg
.wParam
))
2166 emacs_event
->part
= scroll_bar_handle
;
2167 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2168 y
= HIWORD (msg
->msg
.wParam
);
2171 emacs_event
->part
= scroll_bar_down_arrow
;
2172 if (y
< top_range
) y
++;
2175 emacs_event
->part
= scroll_bar_up_arrow
;
2179 emacs_event
->part
= scroll_bar_above_handle
;
2182 emacs_event
->part
= scroll_bar_below_handle
;
2185 emacs_event
->part
= scroll_bar_handle
;
2189 emacs_event
->part
= scroll_bar_handle
;
2192 case SB_THUMBPOSITION
:
2193 emacs_event
->part
= scroll_bar_handle
;
2200 x_scroll_bar_set_handle (bar
, y
, y
, 0);
2202 XSETINT (emacs_event
->x
, y
);
2203 XSETINT (emacs_event
->y
, top_range
);
2209 /* Return information to the user about the current position of the mouse
2210 on the scroll bar. */
2212 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2214 Lisp_Object
*bar_window
;
2215 enum scroll_bar_part
*part
;
2217 unsigned long *time
;
2219 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2220 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
2221 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2227 *bar_window
= bar
->window
;
2229 pos
= GetScrollPos (w
, SB_CTL
);
2231 switch (LOWORD (last_mouse_scroll_bar_pos
))
2233 case SB_THUMBPOSITION
:
2235 *part
= scroll_bar_handle
;
2236 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2237 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2240 *part
= scroll_bar_handle
;
2244 *part
= scroll_bar_handle
;
2249 XSETINT(*y
, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)));
2252 last_mouse_scroll_bar
= Qnil
;
2254 *time
= last_mouse_movement_time
;
2259 /* The screen has been cleared so we may have changed foreground or
2260 background colors, and the scroll bars may need to be redrawn.
2261 Clear out the scroll bars, and ask for expose events, so we can
2264 x_scroll_bar_clear (f
)
2269 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2270 bar
= XSCROLL_BAR (bar
)->next
)
2272 HWND window
= SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
));
2273 HDC hdc
= GetDC (window
);
2276 GetClientRect (window
, &rect
);
2277 select_palette (f
, hdc
);
2278 win32_clear_rect (f
, hdc
, &rect
);
2279 deselect_palette (f
, hdc
);
2283 show_scroll_bars (f
, how
)
2289 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2290 bar
= XSCROLL_BAR (bar
)->next
)
2292 HWND window
= SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
));
2293 my_show_window (window
, how
);
2298 /* The main Win32 event-reading loop - w32_read_socket. */
2300 /* Timestamp of enter window event. This is only used by w32_read_socket,
2301 but we have to put it out here, since static variables within functions
2302 sometimes don't work. */
2303 static Time enter_timestamp
;
2305 /* Record the last 100 characters stored
2306 to help debug the loss-of-chars-during-GC problem. */
2308 short temp_buffer
[100];
2310 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*);
2312 /* Map a Win32 WM_CHAR message into a KEY_EVENT_RECORD so that
2313 we can use the same routines to handle input in both console
2314 and window modes. */
2317 convert_to_key_event (Win32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2319 eventp
->bKeyDown
= TRUE
;
2320 eventp
->wRepeatCount
= 1;
2321 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2322 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2323 eventp
->uChar
.AsciiChar
= 0;
2324 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2327 /* Return nonzero if the virtual key is a dead key. */
2330 is_dead_key (int wparam
)
2332 unsigned int code
= MapVirtualKey (wparam
, 2);
2334 /* Win95 returns 0x8000, NT returns 0x80000000. */
2335 if ((code
& 0x8000) || (code
& 0x80000000))
2341 /* Read events coming from the Win32 shell.
2342 This routine is called by the SIGIO handler.
2343 We return as soon as there are no more events to be read.
2345 Events representing keys are stored in buffer BUFP,
2346 which can hold up to NUMCHARS characters.
2347 We return the number of characters stored into the buffer,
2348 thus pretending to be `read'.
2350 WAITP is nonzero if we should block until input arrives.
2351 EXPECTED is nonzero if the caller knows input is available.
2353 Some of these messages are reposted back to the message queue since the
2354 system calls the winproc directly in a context where we cannot return the
2355 data nor can we guarantee the state we are in. So if we dispatch them
2356 we will get into an infinite loop. To prevent this from ever happening we
2357 will set a variable to indicate we are in the read_socket call and indicate
2358 which message we are processing since the winproc gets called recursively with different
2359 messages by the system.
2363 w32_read_socket (sd
, bufp
, numchars
, waitp
, expected
)
2365 register struct input_event
*bufp
;
2366 register int numchars
;
2372 int items_pending
; /* How many items are in the X queue. */
2375 int event_found
= 0;
2378 struct win32_display_info
*dpyinfo
= &one_win32_display_info
;
2380 if (interrupt_input_blocked
)
2382 interrupt_input_pending
= 1;
2386 interrupt_input_pending
= 0;
2389 /* So people can tell when we have read the available input. */
2390 input_signal_count
++;
2393 abort (); /* Don't think this happens. */
2395 while (get_next_msg (&msg
, FALSE
))
2397 switch (msg
.msg
.message
)
2400 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2403 win32_clear_rect (f
, NULL
, &msg
.rect
);
2408 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2412 if (f
->async_visible
== 0)
2414 f
->async_visible
= 1;
2415 f
->async_iconified
= 0;
2416 SET_FRAME_GARBAGED (f
);
2423 msg
.rect
.right
-msg
.rect
.left
+1,
2424 msg
.rect
.bottom
-msg
.rect
.top
+1);
2431 case WM_PALETTECHANGED
:
2432 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2434 /* Realize palette - will force update if needed. */
2435 release_frame_dc (f
, get_frame_dc (f
));
2439 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2441 if (f
&& !f
->iconified
)
2443 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2445 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2446 bufp
->kind
= non_ascii_keystroke
;
2447 bufp
->code
= msg
.msg
.wParam
;
2448 bufp
->modifiers
= win32_kbd_mods_to_emacs (msg
.dwModifiers
);
2449 XSETFRAME (bufp
->frame_or_window
, f
);
2450 bufp
->timestamp
= msg
.msg
.time
;
2458 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2460 if (f
&& !f
->iconified
)
2465 KEY_EVENT_RECORD key
, *keyp
= &key
;
2467 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2470 convert_to_key_event (&msg
, keyp
);
2471 add
= key_event (keyp
, bufp
);
2472 XSETFRAME (bufp
->frame_or_window
, f
);
2475 /* The key pressed generated two characters, most likely
2476 an accent character and a key that could not be
2477 combined with it. Prepend the message on the queue
2478 again to process the second character (which is
2479 being held internally in key_event), and process
2480 the first character now. */
2485 /* Throw dead keys away. */
2486 if (is_dead_key (msg
.msg
.wParam
))
2500 if (dpyinfo
->grabbed
&& last_mouse_frame
2501 && FRAME_LIVE_P (last_mouse_frame
))
2502 f
= last_mouse_frame
;
2504 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2507 note_mouse_movement (f
, &msg
.msg
);
2509 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
2512 case WM_LBUTTONDOWN
:
2514 case WM_MBUTTONDOWN
:
2516 case WM_RBUTTONDOWN
:
2522 if (dpyinfo
->grabbed
&& last_mouse_frame
2523 && FRAME_LIVE_P (last_mouse_frame
))
2524 f
= last_mouse_frame
;
2526 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2530 if ((!dpyinfo
->win32_focus_frame
|| f
== dpyinfo
->win32_focus_frame
)
2533 construct_mouse_click (bufp
, &msg
, f
);
2540 parse_button (msg
.msg
.message
, &button
, &up
);
2544 dpyinfo
->grabbed
&= ~ (1 << button
);
2548 dpyinfo
->grabbed
|= (1 << button
);
2549 last_mouse_frame
= f
;
2556 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2558 if (bar
&& numchars
>= 1)
2560 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2571 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2573 if (f
&& !f
->async_iconified
)
2575 f
->output_data
.win32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2576 f
->output_data
.win32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2581 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2583 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2591 GetClientRect(msg
.msg
.hwnd
, &rect
);
2593 height
= rect
.bottom
- rect
.top
+ 1;
2594 width
= rect
.right
- rect
.left
+ 1;
2596 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2597 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2599 /* Even if the number of character rows and columns has
2600 not changed, the font size may have changed, so we need
2601 to check the pixel dimensions as well. */
2603 if (columns
!= f
->width
2604 || rows
!= f
->height
2605 || width
!= f
->output_data
.win32
->pixel_width
2606 || height
!= f
->output_data
.win32
->pixel_height
)
2608 /* I had set this to 0, 0 - I am not sure why?? */
2610 change_frame_size (f
, rows
, columns
, 0, 1);
2611 SET_FRAME_GARBAGED (f
);
2613 f
->output_data
.win32
->pixel_width
= width
;
2614 f
->output_data
.win32
->pixel_height
= height
;
2615 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
2622 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2624 if (msg
.msg
.message
== WM_SETFOCUS
)
2626 x_new_focus_frame (dpyinfo
, f
);
2628 else if (f
== dpyinfo
->win32_focus_frame
)
2629 x_new_focus_frame (dpyinfo
, 0);
2633 switch (msg
.msg
.wParam
)
2636 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2643 bufp
->kind
= delete_window_event
;
2644 XSETFRAME (bufp
->frame_or_window
, f
);
2652 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2656 f
->async_visible
= 1;
2657 f
->async_iconified
= 1;
2659 bufp
->kind
= iconify_event
;
2660 XSETFRAME (bufp
->frame_or_window
, f
);
2669 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2673 f
->async_visible
= 1;
2674 f
->async_iconified
= 0;
2676 /* wait_reading_process_input will notice this and update
2677 the frame's display structures. */
2678 SET_FRAME_GARBAGED (f
);
2682 bufp
->kind
= deiconify_event
;
2683 XSETFRAME (bufp
->frame_or_window
, f
);
2689 /* Force a redisplay sooner or later
2690 to update the frame titles
2691 in case this is the second frame. */
2692 record_asynch_buffer_change ();
2700 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2707 bufp
->kind
= delete_window_event
;
2708 XSETFRAME (bufp
->frame_or_window
, f
);
2716 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2720 if (msg
.msg
.lParam
== 0)
2722 /* Came from window menu */
2724 extern Lisp_Object
get_frame_menubar_event ();
2725 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2726 struct input_event buf
;
2729 XSETFRAME (frame
, f
);
2730 buf
.kind
= menu_bar_event
;
2732 /* Store initial menu bar event */
2736 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2737 kbd_buffer_store_event (&buf
);
2740 /* Enqueue the events */
2742 while (!NILP (event
))
2744 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2745 kbd_buffer_store_event (&buf
);
2746 event
= XCONS (event
)->cdr
;
2751 /* Came from popup menu */
2758 /* If the focus was just given to an autoraising frame,
2760 /* ??? This ought to be able to handle more than one such frame. */
2761 if (pending_autoraise_frame
)
2763 x_raise_frame (pending_autoraise_frame
);
2764 pending_autoraise_frame
= 0;
2771 /* Drawing the cursor. */
2774 /* Draw a hollow box cursor. Don't change the inside of the box. */
2784 hdc
= get_frame_dc (f
);
2786 hb
= CreateSolidBrush (f
->output_data
.win32
->cursor_pixel
);
2788 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2789 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2790 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.win32
->font
);
2791 rect
.bottom
= rect
.top
+ f
->output_data
.win32
->line_height
;
2793 FrameRect (hdc
, &rect
, hb
);
2796 release_frame_dc (f
, hdc
);
2799 /* Clear the cursor of frame F to background color,
2800 and mark the cursor as not shown.
2801 This is used when the text where the cursor is
2802 is about to be rewritten. */
2808 if (! FRAME_VISIBLE_P (f
)
2809 || f
->phys_cursor_x
< 0)
2812 x_display_cursor (f
, 0);
2813 f
->phys_cursor_x
= -1;
2816 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2817 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2821 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2828 CHAR_TO_PIXEL_COL (f
, column
),
2829 CHAR_TO_PIXEL_ROW (f
, row
),
2830 &glyph
, 1, highlight
, 0);
2834 x_display_bar_cursor (f
, on
)
2838 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2840 /* This is pointless on invisible frames, and dangerous on garbaged
2841 frames; in the latter case, the frame may be in the midst of
2842 changing its size, and curs_x and curs_y may be off the frame. */
2843 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2846 if (! on
&& f
->phys_cursor_x
< 0)
2849 /* If we're not updating, then we want to use the current frame's
2850 cursor position, not our local idea of where the cursor ought to be. */
2851 if (f
!= updating_frame
)
2853 curs_x
= FRAME_CURSOR_X (f
);
2854 curs_y
= FRAME_CURSOR_Y (f
);
2857 /* If there is anything wrong with the current cursor state, remove it. */
2858 if (f
->phys_cursor_x
>= 0
2860 || f
->phys_cursor_x
!= curs_x
2861 || f
->phys_cursor_y
!= curs_y
2862 || f
->output_data
.win32
->current_cursor
!= bar_cursor
))
2864 /* Erase the cursor by redrawing the character underneath it. */
2865 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2866 f
->phys_cursor_glyph
,
2867 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2868 f
->phys_cursor_x
= -1;
2871 /* If we now need a cursor in the new place or in the new form, do it so. */
2873 && (f
->phys_cursor_x
< 0
2874 || (f
->output_data
.win32
->current_cursor
!= bar_cursor
)))
2876 f
->phys_cursor_glyph
2877 = ((current_glyphs
->enable
[curs_y
]
2878 && curs_x
< current_glyphs
->used
[curs_y
])
2879 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2881 win32_fill_area (f
, NULL
, f
->output_data
.win32
->cursor_pixel
,
2882 CHAR_TO_PIXEL_COL (f
, curs_x
),
2883 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2884 max (f
->output_data
.win32
->cursor_width
, 1),
2885 f
->output_data
.win32
->line_height
);
2887 f
->phys_cursor_x
= curs_x
;
2888 f
->phys_cursor_y
= curs_y
;
2890 f
->output_data
.win32
->current_cursor
= bar_cursor
;
2895 /* Turn the displayed cursor of frame F on or off according to ON.
2896 If ON is nonzero, where to put the cursor is specified
2897 by F->cursor_x and F->cursor_y. */
2900 x_display_box_cursor (f
, on
)
2904 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2906 /* This is pointless on invisible frames, and dangerous on garbaged
2907 frames; in the latter case, the frame may be in the midst of
2908 changing its size, and curs_x and curs_y may be off the frame. */
2909 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2912 /* If cursor is off and we want it off, return quickly. */
2913 if (!on
&& f
->phys_cursor_x
< 0)
2916 /* If we're not updating, then we want to use the current frame's
2917 cursor position, not our local idea of where the cursor ought to be. */
2918 if (f
!= updating_frame
)
2920 curs_x
= FRAME_CURSOR_X (f
);
2921 curs_y
= FRAME_CURSOR_Y (f
);
2924 /* If cursor is currently being shown and we don't want it to be
2925 or it is in the wrong place,
2926 or we want a hollow box and it's not so, (pout!)
2928 if (f
->phys_cursor_x
>= 0
2930 || f
->phys_cursor_x
!= curs_x
2931 || f
->phys_cursor_y
!= curs_y
2932 || (f
->output_data
.win32
->current_cursor
!= hollow_box_cursor
2933 && (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
))))
2935 int mouse_face_here
= 0;
2936 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2938 /* If the cursor is in the mouse face area, redisplay that when
2939 we clear the cursor. */
2940 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2942 (f
->phys_cursor_y
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2943 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2944 && f
->phys_cursor_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2946 (f
->phys_cursor_y
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2947 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2948 && f
->phys_cursor_x
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2949 /* Don't redraw the cursor's spot in mouse face
2950 if it is at the end of a line (on a newline).
2951 The cursor appears there, but mouse highlighting does not. */
2952 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2953 mouse_face_here
= 1;
2955 /* If the font is not as tall as a whole line,
2956 we must explicitly clear the line's whole height. */
2957 if (FONT_HEIGHT (f
->output_data
.win32
->font
) != f
->output_data
.win32
->line_height
)
2958 win32_clear_area (f
, NULL
,
2959 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2960 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2961 FONT_WIDTH (f
->output_data
.win32
->font
),
2962 f
->output_data
.win32
->line_height
);
2963 /* Erase the cursor by redrawing the character underneath it. */
2964 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2965 f
->phys_cursor_glyph
,
2968 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2969 f
->phys_cursor_x
= -1;
2972 /* If we want to show a cursor,
2973 or we want a box cursor and it's not so,
2974 write it in the right place. */
2976 && (f
->phys_cursor_x
< 0
2977 || (f
->output_data
.win32
->current_cursor
!= filled_box_cursor
2978 && f
== FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)))
2980 f
->phys_cursor_glyph
2981 = ((current_glyphs
->enable
[curs_y
]
2982 && curs_x
< current_glyphs
->used
[curs_y
])
2983 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2985 if (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)
2988 f
->output_data
.win32
->current_cursor
= hollow_box_cursor
;
2992 x_draw_single_glyph (f
, curs_y
, curs_x
,
2993 f
->phys_cursor_glyph
, 2);
2994 f
->output_data
.win32
->current_cursor
= filled_box_cursor
;
2997 f
->phys_cursor_x
= curs_x
;
2998 f
->phys_cursor_y
= curs_y
;
3002 x_display_cursor (f
, on
)
3008 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3009 x_display_box_cursor (f
, on
);
3010 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3011 x_display_bar_cursor (f
, on
);
3013 /* Those are the only two we have implemented! */
3019 /* Changing the font of the frame. */
3021 /* Give frame F the font named FONTNAME as its default font, and
3022 return the full name of that font. FONTNAME may be a wildcard
3023 pattern; in that case, we choose some font that fits the pattern.
3024 The return value shows which font we chose. */
3027 x_new_font (f
, fontname
)
3029 register char *fontname
;
3032 int n_matching_fonts
;
3033 XFontStruct
*font_info
;
3034 char new_font_name
[101];
3036 /* Get a font which matches this name */
3040 if (!x_to_win32_font(fontname
, &lf
)
3041 || !win32_to_x_font(&lf
, new_font_name
, 100))
3047 /* See if we've already loaded a matching font. */
3048 already_loaded
= -1;
3053 for (i
= 0; i
< FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3054 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3057 fontname
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3062 /* If we have, just return it from the table. */
3063 if (already_loaded
>= 0)
3064 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3065 /* Otherwise, load the font and add it to the table. */
3071 font
= win32_load_font(FRAME_WIN32_DISPLAY_INFO (f
), fontname
);
3078 /* Do we need to create the table? */
3079 if (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
== 0)
3081 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
= 16;
3082 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3083 = (struct font_info
*) xmalloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3084 * sizeof (struct font_info
));
3086 /* Do we need to grow the table? */
3087 else if (FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
3088 >= FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
)
3090 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3091 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3092 = (struct font_info
*) xrealloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
,
3093 (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3094 * sizeof (struct font_info
)));
3097 n_fonts
= FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
;
3098 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3099 bcopy (fontname
, FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3100 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3101 FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
++;
3104 /* Compute the scroll bar width in character columns. */
3105 if (f
->scroll_bar_pixel_width
> 0)
3107 int wid
= FONT_WIDTH (f
->output_data
.win32
->font
);
3108 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3111 f
->scroll_bar_cols
= 2;
3113 /* Now make the frame display the given font. */
3114 if (FRAME_WIN32_WINDOW (f
) != 0)
3116 frame_update_line_height (f
);
3117 x_set_window_size (f
, 0, f
->width
, f
->height
);
3120 /* If we are setting a new frame's font for the first time,
3121 there are no faces yet, so this font's height is the line height. */
3122 f
->output_data
.win32
->line_height
= FONT_HEIGHT (f
->output_data
.win32
->font
);
3125 Lisp_Object lispy_name
;
3127 lispy_name
= build_string (fontname
);
3133 x_calc_absolute_position (f
)
3138 int flags
= f
->output_data
.win32
->size_hint_flags
;
3142 /* Find the position of the outside upper-left corner of
3143 the inner window, with respect to the outer window. */
3144 if (f
->output_data
.win32
->parent_desc
!= FRAME_WIN32_DISPLAY_INFO (f
)->root_window
)
3147 MapWindowPoints (FRAME_WIN32_WINDOW (f
),
3148 f
->output_data
.win32
->parent_desc
,
3155 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3158 AdjustWindowRect(&rt
, f
->output_data
.win32
->dwStyle
,
3159 FRAME_EXTERNAL_MENU_BAR (f
));
3162 pt
.x
+= (rt
.right
- rt
.left
);
3163 pt
.y
+= (rt
.bottom
- rt
.top
);
3166 /* Treat negative positions as relative to the leftmost bottommost
3167 position that fits on the screen. */
3168 if (flags
& XNegative
)
3169 f
->output_data
.win32
->left_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->width
3170 - 2 * f
->output_data
.win32
->border_width
- pt
.x
3172 + f
->output_data
.win32
->left_pos
);
3174 if (flags
& YNegative
)
3175 f
->output_data
.win32
->top_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->height
3176 - 2 * f
->output_data
.win32
->border_width
- pt
.y
3178 + f
->output_data
.win32
->top_pos
);
3179 /* The left_pos and top_pos
3180 are now relative to the top and left screen edges,
3181 so the flags should correspond. */
3182 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3185 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3186 to really change the position, and 0 when calling from
3187 x_make_frame_visible (in that case, XOFF and YOFF are the current
3188 position values). It is -1 when calling from x_set_frame_parameters,
3189 which means, do adjust for borders but don't change the gravity. */
3191 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3193 register int xoff
, yoff
;
3196 int modified_top
, modified_left
;
3198 if (change_gravity
> 0)
3200 f
->output_data
.win32
->top_pos
= yoff
;
3201 f
->output_data
.win32
->left_pos
= xoff
;
3202 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3204 f
->output_data
.win32
->size_hint_flags
|= XNegative
;
3206 f
->output_data
.win32
->size_hint_flags
|= YNegative
;
3207 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3209 x_calc_absolute_position (f
);
3212 x_wm_set_size_hint (f
, (long) 0, 0);
3214 /* It is a mystery why we need to add the border_width here
3215 when the frame is already visible, but experiment says we do. */
3216 modified_left
= f
->output_data
.win32
->left_pos
;
3217 modified_top
= f
->output_data
.win32
->top_pos
;
3218 if (change_gravity
!= 0)
3220 modified_left
+= f
->output_data
.win32
->border_width
;
3221 modified_top
+= f
->output_data
.win32
->border_width
;
3224 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3226 modified_left
, modified_top
,
3228 SWP_NOZORDER
| SWP_NOSIZE
);
3232 /* Call this to change the size of frame F's x-window.
3233 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3234 for this size change and subsequent size changes.
3235 Otherwise we leave the window gravity unchanged. */
3237 x_set_window_size (f
, change_gravity
, cols
, rows
)
3242 int pixelwidth
, pixelheight
;
3246 check_frame_size (f
, &rows
, &cols
);
3247 f
->output_data
.win32
->vertical_scroll_bar_extra
3248 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3250 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3251 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3252 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
3253 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3254 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3256 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3257 x_wm_set_size_hint (f
, (long) 0, 0);
3262 rect
.left
= rect
.top
= 0;
3263 rect
.right
= pixelwidth
;
3264 rect
.bottom
= pixelheight
;
3266 AdjustWindowRect(&rect
, f
->output_data
.win32
->dwStyle
,
3267 FRAME_EXTERNAL_MENU_BAR (f
));
3269 /* All windows have an extra pixel */
3271 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3274 rect
.right
- rect
.left
+ 1,
3275 rect
.bottom
- rect
.top
+ 1,
3276 SWP_NOZORDER
| SWP_NOMOVE
);
3279 /* Now, strictly speaking, we can't be sure that this is accurate,
3280 but the window manager will get around to dealing with the size
3281 change request eventually, and we'll hear how it went when the
3282 ConfigureNotify event gets here.
3284 We could just not bother storing any of this information here,
3285 and let the ConfigureNotify event set everything up, but that
3286 might be kind of confusing to the lisp code, since size changes
3287 wouldn't be reported in the frame parameters until some random
3288 point in the future when the ConfigureNotify event arrives. */
3289 change_frame_size (f
, rows
, cols
, 0, 0);
3290 PIXEL_WIDTH (f
) = pixelwidth
;
3291 PIXEL_HEIGHT (f
) = pixelheight
;
3293 /* If cursor was outside the new size, mark it as off. */
3294 if (f
->phys_cursor_y
>= rows
3295 || f
->phys_cursor_x
>= cols
)
3297 f
->phys_cursor_x
= -1;
3298 f
->phys_cursor_y
= -1;
3301 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3302 receive in the ConfigureNotify event; if we get what we asked
3303 for, then the event won't cause the screen to become garbaged, so
3304 we have to make sure to do it here. */
3305 SET_FRAME_GARBAGED (f
);
3310 /* Mouse warping. */
3313 x_set_mouse_position (f
, x
, y
)
3319 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.win32
->font
) / 2;
3320 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.win32
->line_height
/ 2;
3322 if (pix_x
< 0) pix_x
= 0;
3323 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3325 if (pix_y
< 0) pix_y
= 0;
3326 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3330 SetCursorPos (pix_x
, pix_y
);
3335 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
3338 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3344 SetCursorPos (pix_x
, pix_y
);
3349 /* focus shifting, raising and lowering. */
3351 x_focus_on_frame (f
)
3361 /* Raise frame F. */
3366 // if (f->async_visible)
3369 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3372 SWP_NOSIZE
| SWP_NOMOVE
);
3377 /* Lower frame F. */
3382 // if (f->async_visible)
3385 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3388 SWP_NOSIZE
| SWP_NOMOVE
);
3394 win32_frame_raise_lower (f
, raise
)
3404 /* Change of visibility. */
3406 /* This tries to wait until the frame is really visible.
3407 However, if the window manager asks the user where to position
3408 the frame, this will return before the user finishes doing that.
3409 The frame will not actually be visible at that time,
3410 but it will become visible later when the window manager
3411 finishes with it. */
3413 x_make_frame_visible (f
)
3418 if (! FRAME_VISIBLE_P (f
))
3420 /* We test FRAME_GARBAGED_P here to make sure we don't
3421 call x_set_offset a second time
3422 if we get to x_make_frame_visible a second time
3423 before the window gets really visible. */
3424 if (! FRAME_ICONIFIED_P (f
)
3425 && ! f
->output_data
.win32
->asked_for_visible
)
3427 x_set_offset (f
, f
->output_data
.win32
->left_pos
, f
->output_data
.win32
->top_pos
, 0);
3428 // SetForegroundWindow (FRAME_WIN32_WINDOW (f));
3431 f
->output_data
.win32
->asked_for_visible
= 1;
3433 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWNORMAL
);
3436 /* Synchronize to ensure Emacs knows the frame is visible
3437 before we do anything else. We do this loop with input not blocked
3438 so that incoming events are handled. */
3441 int count
= input_signal_count
;
3443 /* This must come after we set COUNT. */
3446 XSETFRAME (frame
, f
);
3450 /* Once we have handled input events,
3451 we should have received the MapNotify if one is coming.
3452 So if we have not got it yet, stop looping.
3453 Some window managers make their own decisions
3454 about visibility. */
3455 if (input_signal_count
!= count
)
3457 /* Machines that do polling rather than SIGIO have been observed
3458 to go into a busy-wait here. So we'll fake an alarm signal
3459 to let the handler know that there's something to be read.
3460 We used to raise a real alarm, but it seems that the handler
3461 isn't always enabled here. This is probably a bug. */
3462 if (input_polling_used ())
3464 /* It could be confusing if a real alarm arrives while processing
3465 the fake one. Turn it off and let the handler reset it. */
3467 input_poll_signal ();
3469 /* Once we have handled input events,
3470 we should have received the MapNotify if one is coming.
3471 So if we have not got it yet, stop looping.
3472 Some window managers make their own decisions
3473 about visibility. */
3474 if (input_signal_count
!= count
)
3477 FRAME_SAMPLE_VISIBILITY (f
);
3481 /* Change from mapped state to withdrawn state. */
3483 /* Make the frame visible (mapped and not iconified). */
3485 x_make_frame_invisible (f
)
3490 /* Don't keep the highlight on an invisible frame. */
3491 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3492 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3496 my_show_window (FRAME_WIN32_WINDOW (f
), SW_HIDE
);
3498 /* We can't distinguish this from iconification
3499 just by the event that we get from the server.
3500 So we can't win using the usual strategy of letting
3501 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3502 and synchronize with the server to make sure we agree. */
3504 FRAME_ICONIFIED_P (f
) = 0;
3505 f
->async_visible
= 0;
3506 f
->async_iconified
= 0;
3511 /* Change window state from mapped to iconified. */
3519 /* Don't keep the highlight on an invisible frame. */
3520 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3521 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3523 if (f
->async_iconified
)
3528 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWMINIMIZED
);
3529 /* The frame doesn't seem to be lowered automatically. */
3532 f
->async_iconified
= 1;
3537 /* Destroy the window of frame F. */
3539 x_destroy_window (f
)
3542 struct win32_display_info
*dpyinfo
= FRAME_WIN32_DISPLAY_INFO (f
);
3546 my_destroy_window (f
, FRAME_WIN32_WINDOW (f
));
3547 free_frame_menubar (f
);
3548 free_frame_faces (f
);
3550 xfree (f
->output_data
.win32
);
3551 f
->output_data
.win32
= 0;
3552 if (f
== dpyinfo
->win32_focus_frame
)
3553 dpyinfo
->win32_focus_frame
= 0;
3554 if (f
== dpyinfo
->win32_focus_event_frame
)
3555 dpyinfo
->win32_focus_event_frame
= 0;
3556 if (f
== dpyinfo
->win32_highlight_frame
)
3557 dpyinfo
->win32_highlight_frame
= 0;
3559 dpyinfo
->reference_count
--;
3561 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3563 dpyinfo
->mouse_face_beg_row
3564 = dpyinfo
->mouse_face_beg_col
= -1;
3565 dpyinfo
->mouse_face_end_row
3566 = dpyinfo
->mouse_face_end_col
= -1;
3567 dpyinfo
->mouse_face_window
= Qnil
;
3573 /* Setting window manager hints. */
3575 /* Set the normal size hints for the window manager, for frame F.
3576 FLAGS is the flags word to use--or 0 meaning preserve the flags
3577 that the window now has.
3578 If USER_POSITION is nonzero, we set the USPosition
3579 flag (this is useful when FLAGS is 0). */
3581 x_wm_set_size_hint (f
, flags
, user_position
)
3586 Window window
= FRAME_WIN32_WINDOW (f
);
3588 flexlines
= f
->height
;
3592 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.win32
->font
));
3593 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.win32
->line_height
);
3598 /* Window manager things */
3599 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3604 Window window
= FRAME_WIN32_WINDOW (f
);
3606 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3607 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3608 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3610 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3615 /* Initialization. */
3617 #ifdef USE_X_TOOLKIT
3618 static XrmOptionDescRec emacs_options
[] = {
3619 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3620 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3622 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3623 XrmoptionSepArg
, NULL
},
3624 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3626 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3627 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3628 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3629 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3630 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3631 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3632 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3634 #endif /* USE_X_TOOLKIT */
3636 static int win32_initialized
= 0;
3638 struct win32_display_info
*
3639 win32_term_init (display_name
, xrm_option
, resource_name
)
3640 Lisp_Object display_name
;
3642 char *resource_name
;
3646 struct win32_display_info
*dpyinfo
;
3651 if (!win32_initialized
)
3653 win32_initialize ();
3654 win32_initialized
= 1;
3665 argv
[argc
++] = "-xrm";
3666 argv
[argc
++] = xrm_option
;
3670 dpyinfo
= &one_win32_display_info
;
3672 /* Put this display on the chain. */
3673 dpyinfo
->next
= NULL
;
3675 /* Put it on win32_display_name_list as well, to keep them parallel. */
3676 win32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3677 win32_display_name_list
);
3678 dpyinfo
->name_list_element
= XCONS (win32_display_name_list
)->car
;
3680 dpyinfo
->win32_id_name
3681 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3682 + XSTRING (Vsystem_name
)->size
3684 sprintf (dpyinfo
->win32_id_name
, "%s@%s",
3685 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3688 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3689 resource_name
, EMACS_CLASS
);
3691 /* Put the rdb where we can find it in a way that works on
3693 dpyinfo
->xrdb
= xrdb
;
3695 hdc
= GetDC (GetDesktopWindow ());
3697 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3698 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3699 dpyinfo
->root_window
= GetDesktopWindow ();
3700 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3701 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3702 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3703 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3704 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
3705 dpyinfo
->grabbed
= 0;
3706 dpyinfo
->reference_count
= 0;
3707 dpyinfo
->n_fonts
= 0;
3708 dpyinfo
->font_table_size
= 0;
3709 dpyinfo
->bitmaps
= 0;
3710 dpyinfo
->bitmaps_size
= 0;
3711 dpyinfo
->bitmaps_last
= 0;
3712 dpyinfo
->mouse_face_mouse_frame
= 0;
3713 dpyinfo
->mouse_face_deferred_gc
= 0;
3714 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3715 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3716 dpyinfo
->mouse_face_face_id
= 0;
3717 dpyinfo
->mouse_face_window
= Qnil
;
3718 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3719 dpyinfo
->mouse_face_defer
= 0;
3720 dpyinfo
->win32_focus_frame
= 0;
3721 dpyinfo
->win32_focus_event_frame
= 0;
3722 dpyinfo
->win32_highlight_frame
= 0;
3724 ReleaseDC (GetDesktopWindow (), hdc
);
3726 /* Determine if there is a middle mouse button, to allow parse_button
3727 to decide whether right mouse events should be mouse-2 or
3729 XSETINT (Vwin32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
3731 /* initialise palette with white and black */
3734 defined_color (0, "white", &color
, 1);
3735 defined_color (0, "black", &color
, 1);
3738 #ifndef F_SETOWN_BUG
3740 #ifdef F_SETOWN_SOCK_NEG
3741 /* stdin is a socket here */
3742 fcntl (connection
, F_SETOWN
, -getpid ());
3743 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3744 fcntl (connection
, F_SETOWN
, getpid ());
3745 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3746 #endif /* ! defined (F_SETOWN) */
3747 #endif /* F_SETOWN_BUG */
3750 if (interrupt_input
)
3751 init_sigio (connection
);
3752 #endif /* ! defined (SIGIO) */
3759 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3762 x_delete_display (dpyinfo
)
3763 struct win32_display_info
*dpyinfo
;
3765 /* Discard this display from win32_display_name_list and win32_display_list.
3766 We can't use Fdelq because that can quit. */
3767 if (! NILP (win32_display_name_list
)
3768 && EQ (XCONS (win32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3769 win32_display_name_list
= XCONS (win32_display_name_list
)->cdr
;
3774 tail
= win32_display_name_list
;
3775 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3777 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3778 dpyinfo
->name_list_element
))
3780 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3783 tail
= XCONS (tail
)->cdr
;
3787 /* free palette table */
3789 struct win32_palette_entry
* plist
;
3791 plist
= dpyinfo
->color_list
;
3794 struct win32_palette_entry
* pentry
= plist
;
3795 plist
= plist
->next
;
3798 dpyinfo
->color_list
= NULL
;
3799 if (dpyinfo
->palette
)
3800 DeleteObject(dpyinfo
->palette
);
3802 xfree (dpyinfo
->font_table
);
3803 xfree (dpyinfo
->win32_id_name
);
3806 /* Set up use of Win32. */
3808 DWORD
win_msg_worker ();
3812 clear_frame_hook
= win32_clear_frame
;
3813 clear_end_of_line_hook
= win32_clear_end_of_line
;
3814 ins_del_lines_hook
= win32_ins_del_lines
;
3815 change_line_highlight_hook
= win32_change_line_highlight
;
3816 insert_glyphs_hook
= win32_insert_glyphs
;
3817 write_glyphs_hook
= win32_write_glyphs
;
3818 delete_glyphs_hook
= win32_delete_glyphs
;
3819 ring_bell_hook
= win32_ring_bell
;
3820 reset_terminal_modes_hook
= win32_reset_terminal_modes
;
3821 set_terminal_modes_hook
= win32_set_terminal_modes
;
3822 update_begin_hook
= win32_update_begin
;
3823 update_end_hook
= win32_update_end
;
3824 set_terminal_window_hook
= win32_set_terminal_window
;
3825 read_socket_hook
= w32_read_socket
;
3826 frame_up_to_date_hook
= win32_frame_up_to_date
;
3827 cursor_to_hook
= win32_cursor_to
;
3828 reassert_line_highlight_hook
= win32_reassert_line_highlight
;
3829 mouse_position_hook
= win32_mouse_position
;
3830 frame_rehighlight_hook
= win32_frame_rehighlight
;
3831 frame_raise_lower_hook
= win32_frame_raise_lower
;
3832 set_vertical_scroll_bar_hook
= win32_set_vertical_scroll_bar
;
3833 condemn_scroll_bars_hook
= win32_condemn_scroll_bars
;
3834 redeem_scroll_bar_hook
= win32_redeem_scroll_bar
;
3835 judge_scroll_bars_hook
= win32_judge_scroll_bars
;
3837 scroll_region_ok
= 1; /* we'll scroll partial frames */
3838 char_ins_del_ok
= 0; /* just as fast to write the line */
3839 line_ins_del_ok
= 1; /* we'll just blt 'em */
3840 fast_clear_end_of_line
= 1; /* X does this well */
3841 memory_below_frame
= 0; /* we don't remember what scrolls
3845 /* Try to use interrupt input; if we can't, then start polling. */
3846 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3848 /* Create the window thread - it will terminate itself or when the app terminates */
3852 dwMainThreadId
= GetCurrentThreadId ();
3853 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3854 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3856 /* Wait for thread to start */
3861 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3863 hWinThread
= CreateThread (NULL
, 0,
3864 (LPTHREAD_START_ROUTINE
) win_msg_worker
,
3865 0, 0, &dwWinThreadId
);
3867 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3870 /* It is desirable that mainThread should have the same notion of
3871 focus window and active window as winThread. Unfortunately, the
3872 following call to AttachThreadInput, which should do precisely what
3873 we need, causes major problems when Emacs is linked as a console
3874 program. Unfortunately, we have good reasons for doing that, so
3875 instead we need to send messages to winThread to make some API
3876 calls for us (ones that affect, or depend on, the active/focus
3878 #ifdef ATTACH_THREADS
3879 AttachThreadInput (dwMainThreadId
, dwWinThreadId
, TRUE
);
3884 syms_of_win32term ()
3886 staticpro (&win32_display_name_list
);
3887 win32_display_name_list
= Qnil
;
3889 staticpro (&last_mouse_scroll_bar
);
3890 last_mouse_scroll_bar
= Qnil
;
3892 staticpro (&Qvendor_specific_keysyms
);
3893 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
3895 DEFVAR_INT ("win32-num-mouse-buttons",
3896 &Vwin32_num_mouse_buttons
,
3897 "Number of physical mouse buttons.");
3898 Vwin32_num_mouse_buttons
= Qnil
;
3900 DEFVAR_LISP ("win32-swap-mouse-buttons",
3901 &Vwin32_swap_mouse_buttons
,
3902 "Swap the mapping of middle and right mouse buttons.\n\
3903 When nil, middle button is mouse-2 and right button is mouse-3.");
3904 Vwin32_swap_mouse_buttons
= Qnil
;