1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
27 #include "blockinput.h"
39 #include "character.h"
43 #include "dispextern.h"
45 #include "termhooks.h"
52 #include "intervals.h"
65 static int max_fringe_bmp
= 0;
66 static HBITMAP
*fringe_bmp
= 0;
68 /* Non-nil means Emacs uses toolkit scroll bars. */
70 Lisp_Object Vx_toolkit_scroll_bars
;
72 /* Temporary variables for w32_read_socket. */
74 static int last_mousemove_x
= 0;
75 static int last_mousemove_y
= 0;
77 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
78 #ifndef GET_WHEEL_DELTA_WPARAM
79 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
82 /* Non-zero means that a HELP_EVENT has been generated since Emacs
85 static int any_help_event_p
;
87 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88 static Lisp_Object last_window
;
90 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
91 int x_use_underline_position_properties
;
93 /* Non-zero means to draw the underline at the same place as the descent line. */
95 int x_underline_at_descent_line
;
97 extern unsigned int msh_mousewheel
;
99 extern void free_frame_menubar ();
101 extern int w32_codepage_for_font (char *fontname
);
102 extern Cursor
w32_load_cursor (LPCTSTR name
);
104 extern Lisp_Object Vwindow_system
;
106 #define x_any_window_to_frame x_window_to_frame
107 #define x_top_window_to_frame x_window_to_frame
110 /* This is display since w32 does not support multiple ones. */
111 struct w32_display_info one_w32_display_info
;
112 struct w32_display_info
*x_display_list
;
114 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
115 one for each element of w32_display_list and in the same order.
116 NAME is the name of the frame.
117 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
118 Lisp_Object w32_display_name_list
;
122 /* Pre Windows 2000, this was not available, but define it here so
123 that Emacs compiled on such a platform will run on newer versions. */
125 typedef struct tagWCRANGE
131 typedef struct tagGLYPHSET
135 DWORD cGlyphsSupported
;
142 /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
143 BOOL (WINAPI
*pfnSetLayeredWindowAttributes
) (HWND
, COLORREF
, BYTE
, DWORD
);
146 #define LWA_ALPHA 0x02
148 /* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
149 later targets by MSVC headers. */
150 #ifndef WS_EX_LAYERED
151 #define WS_EX_LAYERED 0x80000
154 /* Frame being updated by update_frame. This is declared in term.c.
155 This is set by update_begin and looked at by all the
156 w32 functions. It is zero while not inside an update.
157 In that case, the w32 functions assume that `SELECTED_FRAME ()'
158 is the frame to apply to. */
159 extern struct frame
*updating_frame
;
161 /* This is a frame waiting to be autoraised, within w32_read_socket. */
162 struct frame
*pending_autoraise_frame
;
164 /* The handle of the frame that currently owns the system caret. */
165 HWND w32_system_caret_hwnd
;
166 int w32_system_caret_height
;
167 int w32_system_caret_x
;
168 int w32_system_caret_y
;
169 int w32_use_visible_system_caret
;
171 DWORD dwWindowsThreadId
= 0;
172 HANDLE hWindowsThread
= NULL
;
173 DWORD dwMainThreadId
= 0;
174 HANDLE hMainThread
= NULL
;
176 int vertical_scroll_bar_min_handle
;
177 int vertical_scroll_bar_top_border
;
178 int vertical_scroll_bar_bottom_border
;
180 int last_scroll_bar_drag_pos
;
182 /* Mouse movement. */
184 /* Where the mouse was last time we reported a mouse event. */
185 static RECT last_mouse_glyph
;
186 static FRAME_PTR last_mouse_glyph_frame
;
187 static Lisp_Object last_mouse_press_frame
;
189 int w32_num_mouse_buttons
;
191 Lisp_Object Vw32_swap_mouse_buttons
;
193 /* Control whether x_raise_frame also sets input focus. */
194 Lisp_Object Vw32_grab_focus_on_raise
;
196 /* Control whether Caps Lock affects non-ascii characters. */
197 Lisp_Object Vw32_capslock_is_shiftlock
;
199 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
200 Lisp_Object Vw32_recognize_altgr
;
202 /* The scroll bar in which the last motion event occurred.
204 If the last motion event occurred in a scroll bar, we set this
205 so w32_mouse_position can know whether to report a scroll bar motion or
208 If the last motion event didn't occur in a scroll bar, we set this
209 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
210 static Lisp_Object last_mouse_scroll_bar
;
211 static int last_mouse_scroll_bar_pos
;
213 /* This is a hack. We would really prefer that w32_mouse_position would
214 return the time associated with the position it returns, but there
215 doesn't seem to be any way to wrest the time-stamp from the server
216 along with the position query. So, we just keep track of the time
217 of the last movement we received, and return that in hopes that
218 it's somewhat accurate. */
219 static Time last_mouse_movement_time
;
221 /* Incremented by w32_read_socket whenever it really tries to read
224 static int volatile input_signal_count
;
226 static int input_signal_count
;
229 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
231 /* A mask of extra modifier bits to put into every keyboard char. */
232 extern EMACS_INT extra_keyboard_modifiers
;
234 /* Keyboard code page - may be changed by language-change events. */
235 static int keyboard_codepage
;
237 static void x_update_window_end
P_ ((struct window
*, int, int));
238 static void w32_handle_tool_bar_click
P_ ((struct frame
*,
239 struct input_event
*));
240 static void w32_define_cursor
P_ ((Window
, Cursor
));
242 void x_lower_frame
P_ ((struct frame
*));
243 void x_scroll_bar_clear
P_ ((struct frame
*));
244 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
245 void x_raise_frame
P_ ((struct frame
*));
246 void x_set_window_size
P_ ((struct frame
*, int, int, int));
247 void x_wm_set_window_state
P_ ((struct frame
*, int));
248 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
249 static void w32_initialize
P_ ((void));
250 static void x_update_end
P_ ((struct frame
*));
251 static void w32_frame_up_to_date
P_ ((struct frame
*));
252 static void w32_set_terminal_modes
P_ ((struct terminal
*));
253 static void w32_reset_terminal_modes
P_ ((struct terminal
*));
254 static void x_clear_frame
P_ ((struct frame
*));
255 static void frame_highlight
P_ ((struct frame
*));
256 static void frame_unhighlight
P_ ((struct frame
*));
257 static void x_new_focus_frame
P_ ((struct w32_display_info
*,
259 static void x_focus_changed
P_ ((int, int, struct w32_display_info
*,
260 struct frame
*, struct input_event
*));
261 static void w32_detect_focus_change
P_ ((struct w32_display_info
*,
262 W32Msg
*, struct input_event
*));
263 static void w32_frame_rehighlight
P_ ((struct frame
*));
264 static void x_frame_rehighlight
P_ ((struct w32_display_info
*));
265 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
266 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
267 enum text_cursor_kinds
));
268 static void w32_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, HDC
));
269 static BOOL my_show_window
P_ ((struct frame
*, HWND
, int));
270 static void my_set_window_pos
P_ ((HWND
, HWND
, int, int, int, int, UINT
));
271 static void my_set_focus
P_ ((struct frame
*, HWND
));
272 static void my_set_foreground_window
P_ ((HWND
));
273 static void my_destroy_window
P_ ((struct frame
*, HWND
));
275 static Lisp_Object Qvendor_specific_keysyms
;
278 /***********************************************************************
280 ***********************************************************************/
284 /* This is a function useful for recording debugging information about
285 the sequence of occurrences in this file. */
293 struct record event_record
[100];
295 int event_record_index
;
297 record_event (locus
, type
)
301 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
302 event_record_index
= 0;
304 event_record
[event_record_index
].locus
= locus
;
305 event_record
[event_record_index
].type
= type
;
306 event_record_index
++;
313 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
316 if (mask
& GCForeground
)
317 gc
->foreground
= xgcv
->foreground
;
318 if (mask
& GCBackground
)
319 gc
->background
= xgcv
->background
;
321 gc
->font
= xgcv
->font
;
324 XGCValues
*XCreateGC (void * ignore
, Window window
, unsigned long mask
,
327 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
328 bzero (gc
, sizeof (XGCValues
));
330 XChangeGC (ignore
, gc
, mask
, xgcv
);
336 XGetGCValues (void* ignore
, XGCValues
*gc
,
337 unsigned long mask
, XGCValues
*xgcv
)
339 XChangeGC (ignore
, xgcv
, mask
, gc
);
343 w32_set_clip_rectangle (HDC hdc
, RECT
*rect
)
347 HRGN clip_region
= CreateRectRgnIndirect (rect
);
348 SelectClipRgn (hdc
, clip_region
);
349 DeleteObject (clip_region
);
352 SelectClipRgn (hdc
, NULL
);
356 /* Draw a hollow rectangle at the specified position. */
358 w32_draw_rectangle (HDC hdc
, XGCValues
*gc
, int x
, int y
,
359 int width
, int height
)
364 hb
= CreateSolidBrush (gc
->background
);
365 hp
= CreatePen (PS_SOLID
, 0, gc
->foreground
);
366 oldhb
= SelectObject (hdc
, hb
);
367 oldhp
= SelectObject (hdc
, hp
);
369 Rectangle (hdc
, x
, y
, x
+ width
, y
+ height
);
371 SelectObject (hdc
, oldhb
);
372 SelectObject (hdc
, oldhp
);
377 /* Draw a filled rectangle at the specified position. */
379 w32_fill_rect (f
, hdc
, pix
, lprect
)
387 hb
= CreateSolidBrush (pix
);
388 FillRect (hdc
, lprect
, hb
);
397 HDC hdc
= get_frame_dc (f
);
399 /* Under certain conditions, this can be called at startup with
400 a console frame pointer before the GUI frame is created. An HDC
401 of 0 indicates this. */
404 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
405 w32_clear_rect (f
, hdc
, &rect
);
408 release_frame_dc (f
, hdc
);
411 #define OPAQUE_FRAME 255
414 x_set_frame_alpha (f
)
417 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
419 double alpha_min
= 1.0;
422 HWND window
= FRAME_W32_WINDOW (f
);
424 /* Older versions of Windows do not support transparency. */
425 if (!pfnSetLayeredWindowAttributes
)
428 if (dpyinfo
->x_highlight_frame
== f
)
433 if (FLOATP (Vframe_alpha_lower_limit
))
434 alpha_min
= XFLOAT_DATA (Vframe_alpha_lower_limit
);
435 else if (INTEGERP (Vframe_alpha_lower_limit
))
436 alpha_min
= (XINT (Vframe_alpha_lower_limit
)) / 100.0;
440 else if (alpha
> 1.0)
442 else if (alpha
< alpha_min
&& alpha_min
<= 1.0)
445 opac
= alpha
* OPAQUE_FRAME
;
447 ex_style
= GetWindowLong (window
, GWL_EXSTYLE
);
449 if (opac
== OPAQUE_FRAME
)
450 ex_style
&= ~WS_EX_LAYERED
;
452 ex_style
|= WS_EX_LAYERED
;
454 SetWindowLong (window
, GWL_EXSTYLE
, ex_style
);
456 if (opac
!= OPAQUE_FRAME
)
457 pfnSetLayeredWindowAttributes (window
, 0, opac
, LWA_ALPHA
);
461 x_display_pixel_height (dpyinfo
)
462 struct w32_display_info
*dpyinfo
;
464 HDC dc
= GetDC (NULL
);
465 int pixels
= GetDeviceCaps (dc
, VERTRES
);
466 ReleaseDC (NULL
, dc
);
471 x_display_pixel_width (dpyinfo
)
472 struct w32_display_info
*dpyinfo
;
474 HDC dc
= GetDC (NULL
);
475 int pixels
= GetDeviceCaps (dc
, HORZRES
);
476 ReleaseDC (NULL
, dc
);
481 /***********************************************************************
482 Starting and ending an update
483 ***********************************************************************/
485 /* Start an update of frame F. This function is installed as a hook
486 for update_begin, i.e. it is called when update_begin is called.
487 This function is called prior to calls to x_update_window_begin for
488 each window being updated. */
494 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
496 if (! FRAME_W32_P (f
))
499 /* Regenerate display palette before drawing if list of requested
500 colors has changed. */
501 if (display_info
->regen_palette
)
503 w32_regenerate_palette (f
);
504 display_info
->regen_palette
= FALSE
;
509 /* Start update of window W. Set the global variable updated_window
510 to the window being updated and set output_cursor to the cursor
514 x_update_window_begin (w
)
517 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
518 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
520 /* Hide the system caret during an update. */
521 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
523 SendMessage (w32_system_caret_hwnd
, WM_EMACS_HIDE_CARET
, 0, 0);
527 set_output_cursor (&w
->cursor
);
531 if (f
== display_info
->mouse_face_mouse_frame
)
533 /* Don't do highlighting for mouse motion during the update. */
534 display_info
->mouse_face_defer
= 1;
536 /* If F needs to be redrawn, simply forget about any prior mouse
538 if (FRAME_GARBAGED_P (f
))
539 display_info
->mouse_face_window
= Qnil
;
541 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
542 their mouse_face_p flag set, which means that they are always
543 unequal to rows in a desired matrix which never have that
544 flag set. So, rows containing mouse-face glyphs are never
545 scrolled, and we don't have to switch the mouse highlight off
546 here to prevent it from being scrolled. */
548 /* Can we tell that this update does not affect the window
549 where the mouse highlight is? If so, no need to turn off.
550 Likewise, don't do anything if the frame is garbaged;
551 in that case, the frame's current matrix that we would use
552 is all wrong, and we will redisplay that line anyway. */
553 if (!NILP (display_info
->mouse_face_window
)
554 && w
== XWINDOW (display_info
->mouse_face_window
))
558 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
559 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
562 if (i
< w
->desired_matrix
->nrows
)
563 clear_mouse_face (display_info
);
571 /* Draw a vertical window border from (x,y0) to (x,y1) */
574 w32_draw_vertical_window_border (w
, x
, y0
, y1
)
578 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
588 hdc
= get_frame_dc (f
);
589 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
591 w32_fill_rect (f
, hdc
, face
->foreground
, &r
);
593 w32_fill_rect (f
, hdc
, FRAME_FOREGROUND_PIXEL (f
), &r
);
595 release_frame_dc (f
, hdc
);
599 /* End update of window W (which is equal to updated_window).
601 Draw vertical borders between horizontally adjacent windows, and
602 display W's cursor if CURSOR_ON_P is non-zero.
604 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
605 glyphs in mouse-face were overwritten. In that case we have to
606 make sure that the mouse-highlight is properly redrawn.
608 W may be a menu bar pseudo-window in case we don't have X toolkit
609 support. Such windows don't have a cursor, so don't display it
613 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
615 int cursor_on_p
, mouse_face_overwritten_p
;
617 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
619 if (!w
->pseudo_window_p
)
624 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
626 output_cursor
.x
, output_cursor
.y
);
628 if (draw_window_fringes (w
, 1))
629 x_draw_vertical_border (w
);
634 /* If a row with mouse-face was overwritten, arrange for
635 XTframe_up_to_date to redisplay the mouse highlight. */
636 if (mouse_face_overwritten_p
)
638 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
639 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
640 dpyinfo
->mouse_face_window
= Qnil
;
643 /* Unhide the caret. This won't actually show the cursor, unless it
644 was visible before the corresponding call to HideCaret in
645 x_update_window_begin. */
646 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
648 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
651 updated_window
= NULL
;
655 /* End update of frame F. This function is installed as a hook in
662 if (! FRAME_W32_P (f
))
665 /* Mouse highlight may be displayed again. */
666 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
670 /* This function is called from various places in xdisp.c whenever a
671 complete update has been performed. The global variable
672 updated_window is not available here. */
675 w32_frame_up_to_date (f
)
680 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
682 if (dpyinfo
->mouse_face_deferred_gc
683 || f
== dpyinfo
->mouse_face_mouse_frame
)
686 if (dpyinfo
->mouse_face_mouse_frame
)
687 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
688 dpyinfo
->mouse_face_mouse_x
,
689 dpyinfo
->mouse_face_mouse_y
);
690 dpyinfo
->mouse_face_deferred_gc
= 0;
697 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
698 arrow bitmaps, or clear the fringes if no bitmaps are required
699 before DESIRED_ROW is made current. The window being updated is
700 found in updated_window. This function is called from
701 update_window_line only if it is known that there are differences
702 between bitmaps to be drawn between current row and DESIRED_ROW. */
705 x_after_update_window_line (desired_row
)
706 struct glyph_row
*desired_row
;
708 struct window
*w
= updated_window
;
714 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
715 desired_row
->redraw_fringe_bitmaps_p
= 1;
717 /* When a window has disappeared, make sure that no rest of
718 full-width rows stays visible in the internal border. Could
719 check here if updated_window is the leftmost/rightmost window,
720 but I guess it's not worth doing since vertically split windows
721 are almost never used, internal border is rarely set, and the
722 overhead is very small. */
723 if (windows_or_buffers_changed
724 && desired_row
->full_width_p
725 && (f
= XFRAME (w
->frame
),
726 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
728 && (height
= desired_row
->visible_height
,
731 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
735 HDC hdc
= get_frame_dc (f
);
736 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
737 w32_clear_area (f
, hdc
, FRAME_PIXEL_WIDTH (f
) - width
,
739 release_frame_dc (f
, hdc
);
746 /* Draw the bitmap WHICH in one of the left or right fringes of
747 window W. ROW is the glyph row for which to display the bitmap; it
748 determines the vertical position at which the bitmap has to be
752 w32_draw_fringe_bitmap (w
, row
, p
)
754 struct glyph_row
*row
;
755 struct draw_fringe_bitmap_params
*p
;
757 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
759 struct face
*face
= p
->face
;
762 hdc
= get_frame_dc (f
);
766 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
768 /* If the fringe is adjacent to the left (right) scroll bar of a
769 leftmost (rightmost, respectively) window, then extend its
770 background to the gap between the fringe and the bar. */
771 if ((WINDOW_LEFTMOST_P (w
)
772 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
773 || (WINDOW_RIGHTMOST_P (w
)
774 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
)))
776 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
780 int left
= WINDOW_SCROLL_BAR_AREA_X (w
);
781 int width
= (WINDOW_CONFIG_SCROLL_BAR_COLS (w
)
782 * FRAME_COLUMN_WIDTH (f
));
786 /* Bitmap fills the fringe. */
787 if (left
+ width
== p
->x
)
788 bx
= left
+ sb_width
;
789 else if (p
->x
+ p
->wd
== left
)
793 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
795 nx
= width
- sb_width
;
796 by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
798 ny
= row
->visible_height
;
803 if (left
+ width
== bx
)
805 bx
= left
+ sb_width
;
806 nx
+= width
- sb_width
;
808 else if (bx
+ nx
== left
)
809 nx
+= width
- sb_width
;
814 if (bx
>= 0 && nx
> 0)
815 w32_fill_area (f
, hdc
, face
->background
, bx
, by
, nx
, ny
);
818 /* Must clip because of partially visible lines. */
819 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
822 /* Adjust position of "bottom aligned" bitmap on partially
825 int oldVH
= row
->visible_height
;
826 row
->visible_height
= p
->h
;
827 row
->y
-= rowY
- p
->y
;
828 w32_clip_to_row (w
, row
, -1, hdc
);
830 row
->visible_height
= oldVH
;
833 w32_clip_to_row (w
, row
, -1, hdc
);
835 if (p
->which
&& p
->which
< max_fringe_bmp
)
837 HBITMAP pixmap
= fringe_bmp
[p
->which
];
841 compat_hdc
= CreateCompatibleDC (hdc
);
845 horig_obj
= SelectObject (compat_hdc
, pixmap
);
847 /* Paint overlays transparently. */
850 HBRUSH h_brush
, h_orig_brush
;
852 SetTextColor (hdc
, BLACK_PIX_DEFAULT (f
));
853 SetBkColor (hdc
, WHITE_PIX_DEFAULT (f
));
854 h_brush
= CreateSolidBrush (face
->foreground
);
855 h_orig_brush
= SelectObject (hdc
, h_brush
);
857 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
858 compat_hdc
, 0, p
->dh
,
860 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
861 compat_hdc
, 0, p
->dh
,
863 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
864 compat_hdc
, 0, p
->dh
,
867 SelectObject (hdc
, h_orig_brush
);
868 DeleteObject (h_brush
);
872 SetTextColor (hdc
, face
->background
);
873 SetBkColor (hdc
, (p
->cursor_p
874 ? f
->output_data
.w32
->cursor_pixel
875 : face
->foreground
));
877 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
878 compat_hdc
, 0, p
->dh
,
882 SelectObject (compat_hdc
, horig_obj
);
883 DeleteDC (compat_hdc
);
887 w32_set_clip_rectangle (hdc
, NULL
);
889 release_frame_dc (f
, hdc
);
893 w32_define_fringe_bitmap (which
, bits
, h
, wd
)
895 unsigned short *bits
;
898 if (which
>= max_fringe_bmp
)
900 int i
= max_fringe_bmp
;
901 max_fringe_bmp
= which
+ 20;
902 fringe_bmp
= (HBITMAP
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (HBITMAP
));
903 while (i
< max_fringe_bmp
)
907 fringe_bmp
[which
] = CreateBitmap (wd
, h
, 1, 1, bits
);
911 w32_destroy_fringe_bitmap (which
)
914 if (which
>= max_fringe_bmp
)
917 if (fringe_bmp
[which
])
918 DeleteObject (fringe_bmp
[which
]);
919 fringe_bmp
[which
] = 0;
924 /* This is called when starting Emacs and when restarting after
925 suspend. When starting Emacs, no window is mapped. And nothing
926 must be done to Emacs's own window if it is suspended (though that
930 w32_set_terminal_modes (struct terminal
*term
)
934 /* This is called when exiting or suspending Emacs. Exiting will make
935 the W32 windows go away, and suspending requires no action. */
938 w32_reset_terminal_modes (struct terminal
*term
)
944 /***********************************************************************
946 ***********************************************************************/
948 /* Function prototypes of this page. */
950 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
951 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
952 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
954 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
955 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
956 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
957 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
958 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
959 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
960 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
961 static int w32_alloc_lighter_color (struct frame
*, COLORREF
*, double, int);
962 static void w32_setup_relief_color
P_ ((struct frame
*, struct relief
*,
963 double, int, COLORREF
));
964 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
965 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
966 static void x_draw_image_relief
P_ ((struct glyph_string
*));
967 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
968 static void w32_draw_image_foreground_1
P_ ((struct glyph_string
*, HBITMAP
));
969 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
971 static void w32_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
972 int, int, int, int, int, int,
974 static void w32_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
975 int, int, int, RECT
*));
978 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
983 struct glyph_string
*s
;
985 if (s
->font
== FRAME_FONT (s
->f
)
986 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
987 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
989 s
->gc
= s
->f
->output_data
.w32
->cursor_gc
;
992 /* Cursor on non-default face: must merge. */
996 xgcv
.background
= s
->f
->output_data
.w32
->cursor_pixel
;
997 xgcv
.foreground
= s
->face
->background
;
999 /* If the glyph would be invisible, try a different foreground. */
1000 if (xgcv
.foreground
== xgcv
.background
)
1001 xgcv
.foreground
= s
->face
->foreground
;
1002 if (xgcv
.foreground
== xgcv
.background
)
1003 xgcv
.foreground
= s
->f
->output_data
.w32
->cursor_foreground_pixel
;
1004 if (xgcv
.foreground
== xgcv
.background
)
1005 xgcv
.foreground
= s
->face
->foreground
;
1007 /* Make sure the cursor is distinct from text in this face. */
1008 if (xgcv
.background
== s
->face
->background
1009 && xgcv
.foreground
== s
->face
->foreground
)
1011 xgcv
.background
= s
->face
->foreground
;
1012 xgcv
.foreground
= s
->face
->background
;
1015 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1016 xgcv
.font
= s
->font
;
1017 mask
= GCForeground
| GCBackground
| GCFont
;
1019 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1020 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1023 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1024 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1026 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1031 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1034 x_set_mouse_face_gc (s
)
1035 struct glyph_string
*s
;
1040 /* What face has to be used last for the mouse face? */
1041 face_id
= FRAME_W32_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1042 face
= FACE_FROM_ID (s
->f
, face_id
);
1044 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1046 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1047 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1049 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1050 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1051 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1053 /* If font in this face is same as S->font, use it. */
1054 if (s
->font
== s
->face
->font
)
1055 s
->gc
= s
->face
->gc
;
1058 /* Otherwise construct scratch_cursor_gc with values from FACE
1063 xgcv
.background
= s
->face
->background
;
1064 xgcv
.foreground
= s
->face
->foreground
;
1065 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1066 xgcv
.font
= s
->font
;
1067 mask
= GCForeground
| GCBackground
| GCFont
;
1069 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1070 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1073 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1074 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1076 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1079 xassert (s
->gc
!= 0);
1083 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1084 Faces to use in the mode line have already been computed when the
1085 matrix was built, so there isn't much to do, here. */
1088 x_set_mode_line_face_gc (s
)
1089 struct glyph_string
*s
;
1091 s
->gc
= s
->face
->gc
;
1095 /* Set S->gc of glyph string S for drawing that glyph string. Set
1096 S->stippled_p to a non-zero value if the face of S has a stipple
1100 x_set_glyph_string_gc (s
)
1101 struct glyph_string
*s
;
1103 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1105 if (s
->hl
== DRAW_NORMAL_TEXT
)
1107 s
->gc
= s
->face
->gc
;
1108 s
->stippled_p
= s
->face
->stipple
!= 0;
1110 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1112 x_set_mode_line_face_gc (s
);
1113 s
->stippled_p
= s
->face
->stipple
!= 0;
1115 else if (s
->hl
== DRAW_CURSOR
)
1117 x_set_cursor_gc (s
);
1120 else if (s
->hl
== DRAW_MOUSE_FACE
)
1122 x_set_mouse_face_gc (s
);
1123 s
->stippled_p
= s
->face
->stipple
!= 0;
1125 else if (s
->hl
== DRAW_IMAGE_RAISED
1126 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1128 s
->gc
= s
->face
->gc
;
1129 s
->stippled_p
= s
->face
->stipple
!= 0;
1133 s
->gc
= s
->face
->gc
;
1134 s
->stippled_p
= s
->face
->stipple
!= 0;
1137 /* GC must have been set. */
1138 xassert (s
->gc
!= 0);
1142 /* Set clipping for output of glyph string S. S may be part of a mode
1143 line or menu if we don't have X toolkit support. */
1146 x_set_glyph_string_clipping (s
)
1147 struct glyph_string
*s
;
1150 int n
= get_glyph_string_clip_rects (s
, r
, 2);
1153 w32_set_clip_rectangle (s
->hdc
, r
);
1156 HRGN full_clip
, clip1
, clip2
;
1157 clip1
= CreateRectRgnIndirect (r
);
1158 clip2
= CreateRectRgnIndirect (r
+ 1);
1159 if (CombineRgn (full_clip
, clip1
, clip2
, RGN_OR
) != ERROR
)
1161 SelectClipRgn (s
->hdc
, full_clip
);
1163 DeleteObject (clip1
);
1164 DeleteObject (clip2
);
1165 DeleteObject (full_clip
);
1170 /* Set SRC's clipping for output of glyph string DST. This is called
1171 when we are drawing DST's left_overhang or right_overhang only in
1175 x_set_glyph_string_clipping_exactly (src
, dst
)
1176 struct glyph_string
*src
, *dst
;
1181 r
.right
= r
.left
+ src
->width
;
1183 r
.bottom
= r
.top
+ src
->height
;
1186 w32_set_clip_rectangle (dst
->hdc
, &r
);
1190 Compute left and right overhang of glyph string S. */
1193 w32_compute_glyph_string_overhangs (s
)
1194 struct glyph_string
*s
;
1197 && s
->first_glyph
->type
== CHAR_GLYPH
1198 && !s
->font_not_found_p
)
1200 unsigned *code
= alloca (sizeof (unsigned) * s
->nchars
);
1201 struct font
*font
= s
->font
;
1202 struct font_metrics metrics
;
1205 for (i
= 0; i
< s
->nchars
; i
++)
1206 code
[i
] = s
->char2b
[i
];
1207 font
->driver
->text_extents (font
, code
, s
->nchars
, &metrics
);
1208 s
->right_overhang
= (metrics
.rbearing
> metrics
.width
1209 ? metrics
.rbearing
- metrics
.width
: 0);
1210 s
->left_overhang
= metrics
.lbearing
< 0 ? -metrics
.lbearing
: 0;
1214 s
->right_overhang
= s
->cmp
->rbearing
- s
->cmp
->pixel_width
;
1215 s
->left_overhang
= -s
->cmp
->lbearing
;
1219 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1222 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1223 struct glyph_string
*s
;
1231 /* Take clipping into account. */
1232 if (s
->gc
->clip_mask
== Rect
)
1234 real_x
= max (real_x
, s
->gc
->clip_rectangle
.left
);
1235 real_y
= max (real_y
, s
->gc
->clip_rectangle
.top
);
1236 real_w
= min (real_w
, s
->gc
->clip_rectangle
.right
1237 - s
->gc
->clip_rectangle
.left
);
1238 real_h
= min (real_h
, s
->gc
->clip_rectangle
.bottom
1239 - s
->gc
->clip_rectangle
.top
);
1242 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->background
, real_x
, real_y
,
1247 /* Draw the background of glyph_string S. If S->background_filled_p
1248 is non-zero don't draw it. FORCE_P non-zero means draw the
1249 background even if it wouldn't be drawn normally. This is used
1250 when a string preceding S draws into the background of S, or S
1251 contains the first component of a composition. */
1254 x_draw_glyph_string_background (s
, force_p
)
1255 struct glyph_string
*s
;
1258 /* Nothing to do if background has already been drawn or if it
1259 shouldn't be drawn in the first place. */
1260 if (!s
->background_filled_p
)
1262 int box_line_width
= max (s
->face
->box_line_width
, 0);
1264 #if 0 /* TODO: stipple */
1267 /* Fill background with a stipple pattern. */
1268 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1269 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1270 s
->y
+ box_line_width
,
1271 s
->background_width
,
1272 s
->height
- 2 * box_line_width
);
1273 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1274 s
->background_filled_p
= 1;
1278 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1279 || s
->font_not_found_p
1280 || s
->extends_to_end_of_line_p
1283 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1284 s
->background_width
,
1285 s
->height
- 2 * box_line_width
);
1286 s
->background_filled_p
= 1;
1292 /* Draw the foreground of glyph string S. */
1295 x_draw_glyph_string_foreground (s
)
1296 struct glyph_string
*s
;
1300 /* If first glyph of S has a left box line, start drawing the text
1301 of S to the right of that box line. */
1302 if (s
->face
->box
!= FACE_NO_BOX
1303 && s
->first_glyph
->left_box_line_p
)
1304 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1308 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1309 SetBkColor (s
->hdc
, s
->gc
->background
);
1310 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1312 /* Draw characters of S as rectangles if S's font could not be
1314 if (s
->font_not_found_p
)
1316 for (i
= 0; i
< s
->nchars
; ++i
)
1318 struct glyph
*g
= s
->first_glyph
+ i
;
1320 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1322 x
+= g
->pixel_width
;
1327 struct font
*font
= s
->font
;
1328 int boff
= font
->baseline_offset
;
1332 old_font
= SelectObject (s
->hdc
, FONT_HANDLE (font
));
1334 if (font
->vertical_centering
)
1335 boff
= VCENTER_BASELINE_OFFSET (font
, s
->f
) - boff
;
1337 y
= s
->ybase
- boff
;
1339 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1340 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 0);
1342 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 1);
1343 if (s
->face
->overstrike
)
1344 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, 0);
1346 SelectObject (s
->hdc
, old_font
);
1350 /* Draw the foreground of composite glyph string S. */
1353 x_draw_composite_glyph_string_foreground (s
)
1354 struct glyph_string
*s
;
1357 struct font
*font
= s
->font
;
1359 /* If first glyph of S has a left box line, start drawing the text
1360 of S to the right of that box line. */
1361 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1362 && s
->first_glyph
->left_box_line_p
)
1363 x
= s
->x
+ eabs (s
->face
->box_line_width
);
1367 /* S is a glyph string for a composition. S->cmp_from is the index
1368 of the first character drawn for glyphs of this composition.
1369 S->cmp_from == 0 means we are drawing the very first character of
1370 this composition. */
1372 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1373 SetBkColor (s
->hdc
, s
->gc
->background
);
1374 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1376 /* Draw a rectangle for the composition if the font for the very
1377 first character of the composition could not be loaded. */
1378 if (s
->font_not_found_p
)
1380 if (s
->cmp_from
== 0)
1381 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, s
->width
- 1,
1384 else if (! s
->first_glyph
->u
.cmp
.automatic
)
1390 old_font
= SelectObject (s
->hdc
, FONT_HANDLE (font
));
1392 for (i
= 0, j
= s
->cmp_from
; i
< s
->nchars
; i
++, j
++)
1393 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1395 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1396 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1398 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, 0);
1399 if (s
->face
->overstrike
)
1400 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, 0);
1402 SelectObject (s
->hdc
, old_font
);
1406 Lisp_Object gstring
= composition_gstring_from_id (s
->cmp_id
);
1412 old_font
= SelectObject (s
->hdc
, FONT_HANDLE (font
));
1414 for (i
= j
= s
->cmp_from
; i
< s
->cmp_to
; i
++)
1416 glyph
= LGSTRING_GLYPH (gstring
, i
);
1417 if (NILP (LGLYPH_ADJUSTMENT (glyph
)))
1418 width
+= LGLYPH_WIDTH (glyph
);
1421 int xoff
, yoff
, wadjust
;
1425 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1428 xoff
= LGLYPH_XOFF (glyph
);
1429 yoff
= LGLYPH_YOFF (glyph
);
1430 wadjust
= LGLYPH_WADJUST (glyph
);
1431 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, 0);
1438 font
->driver
->draw (s
, j
, i
, x
, y
, 0);
1440 SelectObject (s
->hdc
, old_font
);
1445 /* Brightness beyond which a color won't have its highlight brightness
1448 Nominally, highlight colors for `3d' faces are calculated by
1449 brightening an object's color by a constant scale factor, but this
1450 doesn't yield good results for dark colors, so for colors who's
1451 brightness is less than this value (on a scale of 0-255) have to
1452 use an additional additive factor.
1454 The value here is set so that the default menu-bar/mode-line color
1455 (grey75) will not have its highlights changed at all. */
1456 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1459 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1460 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1461 If this produces the same color as COLOR, try a color where all RGB
1462 values have DELTA added. Return the allocated color in *COLOR.
1463 DISPLAY is the X display, CMAP is the colormap to operate on.
1464 Value is non-zero if successful. */
1467 w32_alloc_lighter_color (f
, color
, factor
, delta
)
1476 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1479 /* Change RGB values by specified FACTOR. Avoid overflow! */
1480 xassert (factor
>= 0);
1481 new = PALETTERGB (min (0xff, factor
* GetRValue (*color
)),
1482 min (0xff, factor
* GetGValue (*color
)),
1483 min (0xff, factor
* GetBValue (*color
)));
1485 /* Calculate brightness of COLOR. */
1486 bright
= (2 * GetRValue (*color
) + 3 * GetGValue (*color
)
1487 + GetBValue (*color
)) / 6;
1489 /* We only boost colors that are darker than
1490 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1491 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1492 /* Make an additive adjustment to NEW, because it's dark enough so
1493 that scaling by FACTOR alone isn't enough. */
1495 /* How far below the limit this color is (0 - 1, 1 being darker). */
1496 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1497 /* The additive adjustment. */
1498 int min_delta
= delta
* dimness
* factor
/ 2;
1501 new = PALETTERGB (max (0, min (0xff, min_delta
- GetRValue (*color
))),
1502 max (0, min (0xff, min_delta
- GetGValue (*color
))),
1503 max (0, min (0xff, min_delta
- GetBValue (*color
))));
1505 new = PALETTERGB (max (0, min (0xff, min_delta
+ GetRValue (*color
))),
1506 max (0, min (0xff, min_delta
+ GetGValue (*color
))),
1507 max (0, min (0xff, min_delta
+ GetBValue (*color
))));
1511 new = PALETTERGB (max (0, min (0xff, delta
+ GetRValue (*color
))),
1512 max (0, min (0xff, delta
+ GetGValue (*color
))),
1513 max (0, min (0xff, delta
+ GetBValue (*color
))));
1515 /* TODO: Map to palette and retry with delta if same? */
1516 /* TODO: Free colors (if using palette)? */
1526 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1527 colors in COLORS. On W32, we no longer try to map colors to
1530 x_query_colors (f
, colors
, ncolors
)
1537 for (i
= 0; i
< ncolors
; i
++)
1539 DWORD pixel
= colors
[i
].pixel
;
1540 /* Convert to a 16 bit value in range 0 - 0xffff. */
1541 colors
[i
].red
= GetRValue (pixel
) * 257;
1542 colors
[i
].green
= GetGValue (pixel
) * 257;
1543 colors
[i
].blue
= GetBValue (pixel
) * 257;
1548 x_query_color (f
, color
)
1552 x_query_colors (f
, color
, 1);
1556 /* Set up the foreground color for drawing relief lines of glyph
1557 string S. RELIEF is a pointer to a struct relief containing the GC
1558 with which lines will be drawn. Use a color that is FACTOR or
1559 DELTA lighter or darker than the relief's background which is found
1560 in S->f->output_data.x->relief_background. If such a color cannot
1561 be allocated, use DEFAULT_PIXEL, instead. */
1564 w32_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1566 struct relief
*relief
;
1569 COLORREF default_pixel
;
1572 struct w32_output
*di
= f
->output_data
.w32
;
1573 unsigned long mask
= GCForeground
;
1575 COLORREF background
= di
->relief_background
;
1576 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
1578 /* TODO: Free colors (if using palette)? */
1580 /* Allocate new color. */
1581 xgcv
.foreground
= default_pixel
;
1583 if (w32_alloc_lighter_color (f
, &pixel
, factor
, delta
))
1585 relief
->allocated_p
= 1;
1586 xgcv
.foreground
= relief
->pixel
= pixel
;
1589 if (relief
->gc
== 0)
1591 #if 0 /* TODO: stipple */
1592 xgcv
.stipple
= dpyinfo
->gray
;
1595 relief
->gc
= XCreateGC (NULL
, FRAME_W32_WINDOW (f
), mask
, &xgcv
);
1598 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
1602 /* Set up colors for the relief lines around glyph string S. */
1605 x_setup_relief_colors (s
)
1606 struct glyph_string
*s
;
1608 struct w32_output
*di
= s
->f
->output_data
.w32
;
1611 if (s
->face
->use_box_color_for_shadows_p
)
1612 color
= s
->face
->box_color
;
1613 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1615 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1616 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1618 color
= s
->gc
->background
;
1620 if (di
->white_relief
.gc
== 0
1621 || color
!= di
->relief_background
)
1623 di
->relief_background
= color
;
1624 w32_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1625 WHITE_PIX_DEFAULT (s
->f
));
1626 w32_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1627 BLACK_PIX_DEFAULT (s
->f
));
1632 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1633 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1634 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1635 relief. LEFT_P non-zero means draw a relief on the left side of
1636 the rectangle. RIGHT_P non-zero means draw a relief on the right
1637 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1641 w32_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
1642 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
1644 int left_x
, top_y
, right_x
, bottom_y
, width
;
1645 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
1650 HDC hdc
= get_frame_dc (f
);
1653 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1655 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1657 w32_set_clip_rectangle (hdc
, clip_rect
);
1661 for (i
= 0; i
< width
; ++i
)
1662 w32_fill_area (f
, hdc
, gc
.foreground
,
1663 left_x
+ i
* left_p
, top_y
+ i
,
1664 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
1668 for (i
= 0; i
< width
; ++i
)
1669 w32_fill_area (f
, hdc
, gc
.foreground
,
1670 left_x
+ i
, top_y
+ i
, 1,
1671 bottom_y
- top_y
- 2 * i
+ 1);
1674 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1676 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1680 for (i
= 0; i
< width
; ++i
)
1681 w32_fill_area (f
, hdc
, gc
.foreground
,
1682 left_x
+ i
* left_p
, bottom_y
- i
,
1683 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
1687 for (i
= 0; i
< width
; ++i
)
1688 w32_fill_area (f
, hdc
, gc
.foreground
,
1689 right_x
- i
, top_y
+ i
+ 1, 1,
1690 bottom_y
- top_y
- 2 * i
- 1);
1692 w32_set_clip_rectangle (hdc
, NULL
);
1694 release_frame_dc (f
, hdc
);
1698 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1699 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1700 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1701 left side of the rectangle. RIGHT_P non-zero means draw a line
1702 on the right side of the rectangle. CLIP_RECT is the clipping
1703 rectangle to use when drawing. */
1706 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
1707 left_p
, right_p
, clip_rect
)
1708 struct glyph_string
*s
;
1709 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
1712 w32_set_clip_rectangle (s
->hdc
, clip_rect
);
1715 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1716 left_x
, top_y
, right_x
- left_x
+ 1, width
);
1721 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1722 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
1726 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1727 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
1732 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1733 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
1736 w32_set_clip_rectangle (s
->hdc
, NULL
);
1740 /* Draw a box around glyph string S. */
1743 x_draw_glyph_string_box (s
)
1744 struct glyph_string
*s
;
1746 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
1747 int left_p
, right_p
;
1748 struct glyph
*last_glyph
;
1751 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
1752 ? WINDOW_RIGHT_EDGE_X (s
->w
)
1753 : window_box_right (s
->w
, s
->area
));
1755 /* The glyph that may have a right box line. */
1756 last_glyph
= (s
->cmp
|| s
->img
1758 : s
->first_glyph
+ s
->nchars
- 1);
1760 width
= eabs (s
->face
->box_line_width
);
1761 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
1763 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
1765 : min (last_x
, s
->x
+ s
->background_width
) - 1));
1767 bottom_y
= top_y
+ s
->height
- 1;
1769 left_p
= (s
->first_glyph
->left_box_line_p
1770 || (s
->hl
== DRAW_MOUSE_FACE
1772 || s
->prev
->hl
!= s
->hl
)));
1773 right_p
= (last_glyph
->right_box_line_p
1774 || (s
->hl
== DRAW_MOUSE_FACE
1776 || s
->next
->hl
!= s
->hl
)));
1778 get_glyph_string_clip_rect (s
, &clip_rect
);
1780 if (s
->face
->box
== FACE_SIMPLE_BOX
)
1781 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
1782 left_p
, right_p
, &clip_rect
);
1785 x_setup_relief_colors (s
);
1786 w32_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
1787 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
1792 /* Draw foreground of image glyph string S. */
1795 x_draw_image_foreground (s
)
1796 struct glyph_string
*s
;
1799 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
1801 /* If first glyph of S has a left box line, start drawing it to the
1802 right of that line. */
1803 if (s
->face
->box
!= FACE_NO_BOX
1804 && s
->first_glyph
->left_box_line_p
1806 x
+= eabs (s
->face
->box_line_width
);
1808 /* If there is a margin around the image, adjust x- and y-position
1810 if (s
->slice
.x
== 0)
1811 x
+= s
->img
->hmargin
;
1812 if (s
->slice
.y
== 0)
1813 y
+= s
->img
->vmargin
;
1819 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
1820 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
1821 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
1822 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
1823 SetBkColor (compat_hdc
, RGB (255, 255, 255));
1824 SetTextColor (s
->hdc
, RGB (0, 0, 0));
1825 x_set_glyph_string_clipping (s
);
1829 HDC mask_dc
= CreateCompatibleDC (s
->hdc
);
1830 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
1832 SetTextColor (s
->hdc
, RGB (255, 255, 255));
1833 SetBkColor (s
->hdc
, RGB (0, 0, 0));
1835 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1836 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
1837 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1838 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
1839 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1840 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
1842 SelectObject (mask_dc
, mask_orig_obj
);
1847 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1848 SetBkColor (s
->hdc
, s
->gc
->background
);
1850 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1851 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
1853 /* When the image has a mask, we can expect that at
1854 least part of a mouse highlight or a block cursor will
1855 be visible. If the image doesn't have a mask, make
1856 a block cursor visible by drawing a rectangle around
1857 the image. I believe it's looking better if we do
1858 nothing here for mouse-face. */
1859 if (s
->hl
== DRAW_CURSOR
)
1861 int r
= s
->img
->relief
;
1863 w32_draw_rectangle (s
->hdc
, s
->gc
, x
- r
, y
- r
,
1864 s
->slice
.width
+ r
*2 - 1,
1865 s
->slice
.height
+ r
*2 - 1);
1869 w32_set_clip_rectangle (s
->hdc
, NULL
);
1870 SelectObject (s
->hdc
, orig_brush
);
1871 DeleteObject (fg_brush
);
1872 SelectObject (compat_hdc
, orig_obj
);
1873 DeleteDC (compat_hdc
);
1876 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, y
,
1877 s
->slice
.width
- 1, s
->slice
.height
- 1);
1879 RestoreDC (s
->hdc
,-1);
1883 /* Draw a relief around the image glyph string S. */
1886 x_draw_image_relief (s
)
1887 struct glyph_string
*s
;
1889 int x0
, y0
, x1
, y1
, thick
, raised_p
;
1892 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
1894 /* If first glyph of S has a left box line, start drawing it to the
1895 right of that line. */
1896 if (s
->face
->box
!= FACE_NO_BOX
1897 && s
->first_glyph
->left_box_line_p
1899 x
+= eabs (s
->face
->box_line_width
);
1901 /* If there is a margin around the image, adjust x- and y-position
1903 if (s
->slice
.x
== 0)
1904 x
+= s
->img
->hmargin
;
1905 if (s
->slice
.y
== 0)
1906 y
+= s
->img
->vmargin
;
1908 if (s
->hl
== DRAW_IMAGE_SUNKEN
1909 || s
->hl
== DRAW_IMAGE_RAISED
)
1911 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
1912 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
1916 thick
= eabs (s
->img
->relief
);
1917 raised_p
= s
->img
->relief
> 0;
1922 x1
= x
+ s
->slice
.width
+ thick
- 1;
1923 y1
= y
+ s
->slice
.height
+ thick
- 1;
1925 x_setup_relief_colors (s
);
1926 get_glyph_string_clip_rect (s
, &r
);
1927 w32_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
1929 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
1931 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
1936 /* Draw the foreground of image glyph string S to PIXMAP. */
1939 w32_draw_image_foreground_1 (s
, pixmap
)
1940 struct glyph_string
*s
;
1943 HDC hdc
= CreateCompatibleDC (s
->hdc
);
1944 HGDIOBJ orig_hdc_obj
= SelectObject (hdc
, pixmap
);
1946 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
1948 /* If first glyph of S has a left box line, start drawing it to the
1949 right of that line. */
1950 if (s
->face
->box
!= FACE_NO_BOX
1951 && s
->first_glyph
->left_box_line_p
1953 x
+= eabs (s
->face
->box_line_width
);
1955 /* If there is a margin around the image, adjust x- and y-position
1957 if (s
->slice
.x
== 0)
1958 x
+= s
->img
->hmargin
;
1959 if (s
->slice
.y
== 0)
1960 y
+= s
->img
->vmargin
;
1964 HDC compat_hdc
= CreateCompatibleDC (hdc
);
1965 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
1966 HBRUSH orig_brush
= SelectObject (hdc
, fg_brush
);
1967 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
1971 HDC mask_dc
= CreateCompatibleDC (hdc
);
1972 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
1974 SetTextColor (hdc
, RGB (0, 0, 0));
1975 SetBkColor (hdc
, RGB (255, 255, 255));
1976 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1977 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
1978 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1979 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
1980 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1981 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
1983 SelectObject (mask_dc
, mask_orig_obj
);
1988 SetTextColor (hdc
, s
->gc
->foreground
);
1989 SetBkColor (hdc
, s
->gc
->background
);
1991 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
1992 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
1994 /* When the image has a mask, we can expect that at
1995 least part of a mouse highlight or a block cursor will
1996 be visible. If the image doesn't have a mask, make
1997 a block cursor visible by drawing a rectangle around
1998 the image. I believe it's looking better if we do
1999 nothing here for mouse-face. */
2000 if (s
->hl
== DRAW_CURSOR
)
2002 int r
= s
->img
->relief
;
2004 w32_draw_rectangle (hdc
, s
->gc
, x
- r
, y
- r
,
2005 s
->slice
.width
+ r
*2 - 1,
2006 s
->slice
.height
+ r
*2 - 1);
2010 SelectObject (hdc
, orig_brush
);
2011 DeleteObject (fg_brush
);
2012 SelectObject (compat_hdc
, orig_obj
);
2013 DeleteDC (compat_hdc
);
2016 w32_draw_rectangle (hdc
, s
->gc
, x
, y
,
2017 s
->slice
.width
- 1, s
->slice
.height
- 1);
2019 SelectObject (hdc
, orig_hdc_obj
);
2024 /* Draw part of the background of glyph string S. X, Y, W, and H
2025 give the rectangle to draw. */
2028 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2029 struct glyph_string
*s
;
2032 #if 0 /* TODO: stipple */
2035 /* Fill background with a stipple pattern. */
2036 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2037 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2038 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2042 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2046 /* Draw image glyph string S.
2049 s->x +-------------------------
2052 | +-------------------------
2055 | | +-------------------
2061 x_draw_image_glyph_string (s
)
2062 struct glyph_string
*s
;
2065 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
2066 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2070 height
= s
->height
- 2 * box_line_vwidth
;
2072 /* Fill background with face under the image. Do it only if row is
2073 taller than image or if image has a clip mask to reduce
2075 s
->stippled_p
= s
->face
->stipple
!= 0;
2076 if (height
> s
->slice
.height
2080 || s
->img
->pixmap
== 0
2081 || s
->width
!= s
->background_width
)
2084 if (s
->first_glyph
->left_box_line_p
2086 x
+= box_line_hwidth
;
2089 if (s
->slice
.y
== 0)
2090 y
+= box_line_vwidth
;
2092 #if 0 /* TODO: figure out if we need to do this on Windows. */
2095 /* Create a pixmap as large as the glyph string. Fill it
2096 with the background color. Copy the image to it, using
2097 its mask. Copy the temporary pixmap to the display. */
2098 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2099 int depth
= DefaultDepthOfScreen (screen
);
2101 /* Create a pixmap as large as the glyph string. */
2102 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2103 s
->background_width
,
2106 /* Don't clip in the following because we're working on the
2108 XSetClipMask (s
->display
, s
->gc
, None
);
2110 /* Fill the pixmap with the background color/stipple. */
2113 /* Fill background with a stipple pattern. */
2114 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2115 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2116 0, 0, s
->background_width
, s
->height
);
2117 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2122 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2124 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2125 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2126 0, 0, s
->background_width
, s
->height
);
2127 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2132 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2134 s
->background_filled_p
= 1;
2137 /* Draw the foreground. */
2140 w32_draw_image_foreground_1 (s
, pixmap
);
2141 x_set_glyph_string_clipping (s
);
2143 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2144 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2145 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2146 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, pixmap
);
2148 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2149 SetBkColor (s
->hdc
, s
->gc
->background
);
2150 BitBlt (s
->hdc
, s
->x
, s
->y
, s
->background_width
, s
->height
,
2151 compat_hdc
, 0, 0, SRCCOPY
);
2153 SelectObject (s
->hdc
, orig_brush
);
2154 DeleteObject (fg_brush
);
2155 SelectObject (compat_hdc
, orig_obj
);
2156 DeleteDC (compat_hdc
);
2158 DeleteObject (pixmap
);
2162 x_draw_image_foreground (s
);
2164 /* If we must draw a relief around the image, do it. */
2166 || s
->hl
== DRAW_IMAGE_RAISED
2167 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2168 x_draw_image_relief (s
);
2172 /* Draw stretch glyph string S. */
2175 x_draw_stretch_glyph_string (s
)
2176 struct glyph_string
*s
;
2178 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2180 if (s
->hl
== DRAW_CURSOR
2181 && !x_stretch_cursor_p
)
2183 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2184 as wide as the stretch glyph. */
2185 int width
, background_width
= s
->background_width
;
2186 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2190 background_width
-= left_x
- x
;
2193 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
2196 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
2198 /* Clear rest using the GC of the original non-cursor face. */
2199 if (width
< background_width
)
2201 XGCValues
*gc
= s
->face
->gc
;
2203 int w
= background_width
- width
, h
= s
->height
;
2208 if (s
->row
->mouse_face_p
2209 && cursor_in_mouse_face_p (s
->w
))
2211 x_set_mouse_face_gc (s
);
2217 get_glyph_string_clip_rect (s
, &r
);
2218 w32_set_clip_rectangle (hdc
, &r
);
2220 #if 0 /* TODO: stipple */
2221 if (s
->face
->stipple
)
2223 /* Fill background with a stipple pattern. */
2224 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2225 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2226 XSetFillStyle (s
->display
, gc
, FillSolid
);
2231 w32_fill_area (s
->f
, s
->hdc
, gc
->background
, x
, y
, w
, h
);
2235 else if (!s
->background_filled_p
)
2237 int background_width
= s
->background_width
;
2238 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2240 /* Don't draw into left margin, fringe or scrollbar area
2241 except for header line and mode line. */
2242 if (x
< left_x
&& !s
->row
->mode_line_p
)
2244 background_width
-= left_x
- x
;
2247 if (background_width
> 0)
2248 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
2251 s
->background_filled_p
= 1;
2255 /* Draw glyph string S. */
2258 x_draw_glyph_string (s
)
2259 struct glyph_string
*s
;
2261 int relief_drawn_p
= 0;
2263 /* If S draws into the background of its successor, draw the
2264 background of the successor first so that S can draw into it.
2265 This makes S->next use XDrawString instead of XDrawImageString. */
2266 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
2269 struct glyph_string
*next
;
2270 for (width
= 0, next
= s
->next
;
2271 next
&& width
< s
->right_overhang
;
2272 width
+= next
->width
, next
= next
->next
)
2273 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
2275 x_set_glyph_string_gc (next
);
2276 x_set_glyph_string_clipping (next
);
2277 if (next
->first_glyph
->type
== STRETCH_GLYPH
)
2278 x_draw_stretch_glyph_string (next
);
2280 x_draw_glyph_string_background (next
, 1);
2281 next
->num_clips
= 0;
2285 /* Set up S->gc, set clipping and draw S. */
2286 x_set_glyph_string_gc (s
);
2288 /* Draw relief (if any) in advance for char/composition so that the
2289 glyph string can be drawn over it. */
2290 if (!s
->for_overlaps
2291 && s
->face
->box
!= FACE_NO_BOX
2292 && (s
->first_glyph
->type
== CHAR_GLYPH
2293 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2296 x_set_glyph_string_clipping (s
);
2297 x_draw_glyph_string_background (s
, 1);
2298 x_draw_glyph_string_box (s
);
2299 x_set_glyph_string_clipping (s
);
2302 else if (!s
->clip_head
/* draw_glyphs didn't specify a clip mask. */
2304 && ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
2305 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
)))
2306 /* We must clip just this glyph. left_overhang part has already
2307 drawn when s->prev was drawn, and right_overhang part will be
2308 drawn later when s->next is drawn. */
2309 x_set_glyph_string_clipping_exactly (s
, s
);
2311 x_set_glyph_string_clipping (s
);
2313 switch (s
->first_glyph
->type
)
2316 x_draw_image_glyph_string (s
);
2320 x_draw_stretch_glyph_string (s
);
2324 if (s
->for_overlaps
)
2325 s
->background_filled_p
= 1;
2327 x_draw_glyph_string_background (s
, 0);
2328 x_draw_glyph_string_foreground (s
);
2331 case COMPOSITE_GLYPH
:
2332 if (s
->for_overlaps
|| (s
->cmp_from
> 0
2333 && ! s
->first_glyph
->u
.cmp
.automatic
))
2334 s
->background_filled_p
= 1;
2336 x_draw_glyph_string_background (s
, 1);
2337 x_draw_composite_glyph_string_foreground (s
);
2344 if (!s
->for_overlaps
)
2346 /* Draw underline. */
2347 if (s
->face
->underline_p
)
2349 unsigned long thickness
, position
;
2352 if (s
->prev
&& s
->prev
->face
->underline_p
)
2354 /* We use the same underline style as the previous one. */
2355 thickness
= s
->prev
->underline_thickness
;
2356 position
= s
->prev
->underline_position
;
2360 /* Get the underline thickness. Default is 1 pixel. */
2361 if (s
->font
&& s
->font
->underline_thickness
> 0)
2362 thickness
= s
->font
->underline_thickness
;
2365 if (x_underline_at_descent_line
)
2366 position
= (s
->height
- thickness
) - (s
->ybase
- s
->y
);
2369 /* Get the underline position. This is the recommended
2370 vertical offset in pixels from the baseline to the top of
2371 the underline. This is a signed value according to the
2372 specs, and its default is
2374 ROUND ((maximum_descent) / 2), with
2375 ROUND (x) = floor (x + 0.5) */
2377 if (x_use_underline_position_properties
2378 && s
->font
&& s
->font
->underline_position
>= 0)
2379 position
= s
->font
->underline_position
;
2381 position
= (s
->font
->descent
+ 1) / 2;
2383 position
= max (position
, underline_minimum_offset
);
2385 /* Check the sanity of thickness and position. We should
2386 avoid drawing underline out of the current line area. */
2387 if (s
->y
+ s
->height
<= s
->ybase
+ position
)
2388 position
= (s
->height
- 1) - (s
->ybase
- s
->y
);
2389 if (s
->y
+ s
->height
< s
->ybase
+ position
+ thickness
)
2390 thickness
= (s
->y
+ s
->height
) - (s
->ybase
+ position
);
2391 s
->underline_thickness
= thickness
;
2392 s
->underline_position
=position
;
2393 y
= s
->ybase
+ position
;
2394 if (s
->face
->underline_defaulted_p
)
2396 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2401 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2405 /* Draw overline. */
2406 if (s
->face
->overline_p
)
2408 unsigned long dy
= 0, h
= 1;
2410 if (s
->face
->overline_color_defaulted_p
)
2412 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2413 s
->y
+ dy
, s
->width
, h
);
2417 w32_fill_area (s
->f
, s
->hdc
, s
->face
->overline_color
, s
->x
,
2418 s
->y
+ dy
, s
->width
, h
);
2422 /* Draw strike-through. */
2423 if (s
->face
->strike_through_p
2424 && !FONT_TEXTMETRIC(s
->font
).tmStruckOut
)
2426 unsigned long h
= 1;
2427 unsigned long dy
= (s
->height
- h
) / 2;
2429 if (s
->face
->strike_through_color_defaulted_p
)
2431 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
, s
->y
+ dy
,
2436 w32_fill_area (s
->f
, s
->hdc
, s
->face
->strike_through_color
, s
->x
,
2437 s
->y
+ dy
, s
->width
, h
);
2441 /* Draw relief if not yet drawn. */
2442 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2443 x_draw_glyph_string_box (s
);
2447 struct glyph_string
*prev
;
2449 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
2450 if (prev
->hl
!= s
->hl
2451 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
2453 /* As prev was drawn while clipped to its own area, we
2454 must draw the right_overhang part using s->hl now. */
2455 enum draw_glyphs_face save
= prev
->hl
;
2458 x_set_glyph_string_gc (prev
);
2459 x_set_glyph_string_clipping_exactly (s
, prev
);
2460 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
2461 x_draw_glyph_string_foreground (prev
);
2463 x_draw_composite_glyph_string_foreground (prev
);
2464 w32_set_clip_rectangle (prev
->hdc
, NULL
);
2466 prev
->num_clips
= 0;
2472 struct glyph_string
*next
;
2474 for (next
= s
->next
; next
; next
= next
->next
)
2475 if (next
->hl
!= s
->hl
2476 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
2478 /* As next will be drawn while clipped to its own area,
2479 we must draw the left_overhang part using s->hl now. */
2480 enum draw_glyphs_face save
= next
->hl
;
2483 x_set_glyph_string_gc (next
);
2484 x_set_glyph_string_clipping_exactly (s
, next
);
2485 if (next
->first_glyph
->type
== CHAR_GLYPH
)
2486 x_draw_glyph_string_foreground (next
);
2488 x_draw_composite_glyph_string_foreground (next
);
2489 w32_set_clip_rectangle (next
->hdc
, NULL
);
2491 next
->num_clips
= 0;
2496 /* Reset clipping. */
2497 w32_set_clip_rectangle (s
->hdc
, NULL
);
2502 /* Shift display to make room for inserted glyphs. */
2505 w32_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2507 int x
, y
, width
, height
, shift_by
;
2511 hdc
= get_frame_dc (f
);
2512 BitBlt (hdc
, x
+ shift_by
, y
, width
, height
,
2513 hdc
, x
, y
, SRCCOPY
);
2515 release_frame_dc (f
, hdc
);
2519 /* Delete N glyphs at the nominal cursor position. Not implemented
2523 x_delete_glyphs (f
, n
)
2527 if (! FRAME_W32_P (f
))
2534 /* Clear entire frame. If updating_frame is non-null, clear that
2535 frame. Otherwise clear the selected frame. */
2538 x_clear_frame (struct frame
*f
)
2540 if (! FRAME_W32_P (f
))
2543 /* Clearing the frame will erase any cursor, so mark them all as no
2545 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2546 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2547 output_cursor
.x
= -1;
2549 /* We don't set the output cursor here because there will always
2550 follow an explicit cursor_to. */
2553 w32_clear_window (f
);
2555 /* We have to clear the scroll bars, too. If we have changed
2556 colors or something like that, then they should be notified. */
2557 x_scroll_bar_clear (f
);
2563 /* Make audible bell. */
2566 w32_ring_bell (struct frame
*f
)
2570 if (FRAME_W32_P (f
) && visible_bell
)
2573 HWND hwnd
= FRAME_W32_WINDOW (f
);
2575 for (i
= 0; i
< 5; i
++)
2577 FlashWindow (hwnd
, TRUE
);
2580 FlashWindow (hwnd
, FALSE
);
2583 w32_sys_ring_bell (f
);
2589 /* Specify how many text lines, from the top of the window,
2590 should be affected by insert-lines and delete-lines operations.
2591 This, and those operations, are used only within an update
2592 that is bounded by calls to x_update_begin and x_update_end. */
2595 w32_set_terminal_window (n
)
2598 /* This function intentionally left blank. */
2602 /***********************************************************************
2604 ***********************************************************************/
2606 /* Perform an insert-lines or delete-lines operation, inserting N
2607 lines or deleting -N lines at vertical position VPOS. */
2610 x_ins_del_lines (f
, vpos
, n
)
2614 if (! FRAME_W32_P (f
))
2621 /* Scroll part of the display as described by RUN. */
2624 x_scroll_run (w
, run
)
2628 struct frame
*f
= XFRAME (w
->frame
);
2629 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
2630 HWND hwnd
= FRAME_W32_WINDOW (f
);
2633 /* Get frame-relative bounding box of the text display area of W,
2634 without mode lines. Include in this box the left and right
2636 window_box (w
, -1, &x
, &y
, &width
, &height
);
2638 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
2639 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
2640 bottom_y
= y
+ height
;
2644 /* Scrolling up. Make sure we don't copy part of the mode
2645 line at the bottom. */
2646 if (from_y
+ run
->height
> bottom_y
)
2647 height
= bottom_y
- from_y
;
2649 height
= run
->height
;
2650 expect_dirty
= CreateRectRgn (x
, y
+ height
, x
+ width
, bottom_y
);
2654 /* Scolling down. Make sure we don't copy over the mode line.
2656 if (to_y
+ run
->height
> bottom_y
)
2657 height
= bottom_y
- to_y
;
2659 height
= run
->height
;
2660 expect_dirty
= CreateRectRgn (x
, y
, x
+ width
, to_y
);
2665 /* Cursor off. Will be switched on again in x_update_window_end. */
2672 HRGN dirty
= CreateRectRgn (0, 0, 0, 0);
2673 HRGN combined
= CreateRectRgn (0, 0, 0, 0);
2675 from
.left
= to
.left
= x
;
2676 from
.right
= to
.right
= x
+ width
;
2678 from
.bottom
= from_y
+ height
;
2680 to
.bottom
= bottom_y
;
2682 ScrollWindowEx (hwnd
, 0, to_y
- from_y
, &from
, &to
, dirty
,
2683 NULL
, SW_INVALIDATE
);
2685 /* Combine this with what we expect to be dirty. This covers the
2686 case where not all of the region we expect is actually dirty. */
2687 CombineRgn (combined
, dirty
, expect_dirty
, RGN_OR
);
2689 /* If the dirty region is not what we expected, redraw the entire frame. */
2690 if (!EqualRgn (combined
, expect_dirty
))
2691 SET_FRAME_GARBAGED (f
);
2693 DeleteObject (dirty
);
2694 DeleteObject (combined
);
2698 DeleteObject (expect_dirty
);
2703 /***********************************************************************
2705 ***********************************************************************/
2711 x_update_cursor (f
, 1);
2712 x_set_frame_alpha (f
);
2716 frame_unhighlight (f
)
2719 x_update_cursor (f
, 1);
2720 x_set_frame_alpha (f
);
2723 /* The focus has changed. Update the frames as necessary to reflect
2724 the new situation. Note that we can't change the selected frame
2725 here, because the Lisp code we are interrupting might become confused.
2726 Each event gets marked with the frame in which it occurred, so the
2727 Lisp code can tell when the switch took place by examining the events. */
2730 x_new_focus_frame (dpyinfo
, frame
)
2731 struct w32_display_info
*dpyinfo
;
2732 struct frame
*frame
;
2734 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
2736 if (frame
!= dpyinfo
->w32_focus_frame
)
2738 /* Set this before calling other routines, so that they see
2739 the correct value of w32_focus_frame. */
2740 dpyinfo
->w32_focus_frame
= frame
;
2742 if (old_focus
&& old_focus
->auto_lower
)
2743 x_lower_frame (old_focus
);
2745 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
2746 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
2748 pending_autoraise_frame
= 0;
2751 x_frame_rehighlight (dpyinfo
);
2755 /* Handle FocusIn and FocusOut state changes for FRAME.
2756 If FRAME has focus and there exists more than one frame, puts
2757 a FOCUS_IN_EVENT into *BUFP. */
2760 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
2763 struct w32_display_info
*dpyinfo
;
2764 struct frame
*frame
;
2765 struct input_event
*bufp
;
2767 if (type
== WM_SETFOCUS
)
2769 if (dpyinfo
->w32_focus_event_frame
!= frame
)
2771 x_new_focus_frame (dpyinfo
, frame
);
2772 dpyinfo
->w32_focus_event_frame
= frame
;
2774 /* Don't stop displaying the initial startup message
2775 for a switch-frame event we don't need. */
2776 if (NILP (Vterminal_frame
)
2777 && CONSP (Vframe_list
)
2778 && !NILP (XCDR (Vframe_list
)))
2780 bufp
->kind
= FOCUS_IN_EVENT
;
2781 XSETFRAME (bufp
->frame_or_window
, frame
);
2785 frame
->output_data
.x
->focus_state
|= state
;
2787 /* TODO: IME focus? */
2789 else if (type
== WM_KILLFOCUS
)
2791 frame
->output_data
.x
->focus_state
&= ~state
;
2793 if (dpyinfo
->w32_focus_event_frame
== frame
)
2795 dpyinfo
->w32_focus_event_frame
= 0;
2796 x_new_focus_frame (dpyinfo
, 0);
2799 /* TODO: IME focus? */
2804 /* The focus may have changed. Figure out if it is a real focus change,
2805 by checking both FocusIn/Out and Enter/LeaveNotify events.
2807 Returns FOCUS_IN_EVENT event in *BUFP. */
2810 w32_detect_focus_change (dpyinfo
, event
, bufp
)
2811 struct w32_display_info
*dpyinfo
;
2813 struct input_event
*bufp
;
2815 struct frame
*frame
;
2817 frame
= x_any_window_to_frame (dpyinfo
, event
->msg
.hwnd
);
2821 /* On w32, this is only called from focus events, so no switch needed. */
2822 x_focus_changed (event
->msg
.message
,
2823 (event
->msg
.message
== WM_KILLFOCUS
?
2824 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
2825 dpyinfo
, frame
, bufp
);
2829 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2832 x_mouse_leave (dpyinfo
)
2833 struct w32_display_info
*dpyinfo
;
2835 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
2838 /* The focus has changed, or we have redirected a frame's focus to
2839 another frame (this happens when a frame uses a surrogate
2840 mini-buffer frame). Shift the highlight as appropriate.
2842 The FRAME argument doesn't necessarily have anything to do with which
2843 frame is being highlighted or un-highlighted; we only use it to find
2844 the appropriate X display info. */
2847 w32_frame_rehighlight (frame
)
2848 struct frame
*frame
;
2850 if (! FRAME_W32_P (frame
))
2852 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
2856 x_frame_rehighlight (dpyinfo
)
2857 struct w32_display_info
*dpyinfo
;
2859 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
2861 if (dpyinfo
->w32_focus_frame
)
2863 dpyinfo
->x_highlight_frame
2864 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
2865 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
2866 : dpyinfo
->w32_focus_frame
);
2867 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
2869 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
2870 dpyinfo
->x_highlight_frame
= dpyinfo
->w32_focus_frame
;
2874 dpyinfo
->x_highlight_frame
= 0;
2876 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
2879 frame_unhighlight (old_highlight
);
2880 if (dpyinfo
->x_highlight_frame
)
2881 frame_highlight (dpyinfo
->x_highlight_frame
);
2885 /* Keyboard processing - modifier keys, etc. */
2887 /* Convert a keysym to its name. */
2890 x_get_keysym_name (keysym
)
2893 /* Make static so we can always return it */
2894 static char value
[100];
2897 GetKeyNameText (keysym
, value
, 100);
2903 static int codepage_for_locale(LCID locale
)
2907 if (GetLocaleInfo (locale
, LOCALE_IDEFAULTANSICODEPAGE
, cp
, 20) > 0)
2914 /* Mouse clicks and mouse movement. Rah. */
2916 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2917 the state in PUP. XBUTTON provides extra information for extended mouse
2918 button messages. Returns FALSE if unable to parse the message. */
2920 parse_button (message
, xbutton
, pbutton
, pup
)
2931 case WM_LBUTTONDOWN
:
2939 case WM_MBUTTONDOWN
:
2940 if (NILP (Vw32_swap_mouse_buttons
))
2947 if (NILP (Vw32_swap_mouse_buttons
))
2953 case WM_RBUTTONDOWN
:
2954 if (NILP (Vw32_swap_mouse_buttons
))
2961 if (NILP (Vw32_swap_mouse_buttons
))
2967 case WM_XBUTTONDOWN
:
2968 button
= xbutton
+ 2;
2972 button
= xbutton
+ 2;
2980 if (pbutton
) *pbutton
= button
;
2986 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2988 If the event is a button press, then note that we have grabbed
2992 construct_mouse_click (result
, msg
, f
)
2993 struct input_event
*result
;
3000 parse_button (msg
->msg
.message
, HIWORD (msg
->msg
.wParam
),
3003 /* Make the event type NO_EVENT; we'll change that when we decide
3005 result
->kind
= MOUSE_CLICK_EVENT
;
3006 result
->code
= button
;
3007 result
->timestamp
= msg
->msg
.time
;
3008 result
->modifiers
= (msg
->dwModifiers
3013 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
3014 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
3015 XSETFRAME (result
->frame_or_window
, f
);
3021 construct_mouse_wheel (result
, msg
, f
)
3022 struct input_event
*result
;
3029 result
->kind
= msg
->msg
.message
== WM_MOUSEHWHEEL
? HORIZ_WHEEL_EVENT
3032 result
->timestamp
= msg
->msg
.time
;
3034 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3035 forward, away from the user (up); a negative value indicates that
3036 the wheel was rotated backward, toward the user (down). */
3037 delta
= GET_WHEEL_DELTA_WPARAM (msg
->msg
.wParam
);
3039 /* The up and down modifiers indicate if the wheel was rotated up or
3040 down based on WHEEL_DELTA value. */
3041 result
->modifiers
= (msg
->dwModifiers
3042 | ((delta
< 0 ) ? down_modifier
: up_modifier
));
3044 /* With multiple monitors, we can legitimately get negative
3045 coordinates, so cast to short to interpret them correctly. */
3046 p
.x
= (short) LOWORD (msg
->msg
.lParam
);
3047 p
.y
= (short) HIWORD (msg
->msg
.lParam
);
3048 ScreenToClient (msg
->msg
.hwnd
, &p
);
3049 XSETINT (result
->x
, p
.x
);
3050 XSETINT (result
->y
, p
.y
);
3051 XSETFRAME (result
->frame_or_window
, f
);
3057 construct_drag_n_drop (result
, msg
, f
)
3058 struct input_event
*result
;
3070 result
->kind
= DRAG_N_DROP_EVENT
;
3072 result
->timestamp
= msg
->msg
.time
;
3073 result
->modifiers
= msg
->dwModifiers
;
3075 hdrop
= (HDROP
) msg
->msg
.wParam
;
3076 DragQueryPoint (hdrop
, &p
);
3079 p
.x
= LOWORD (msg
->msg
.lParam
);
3080 p
.y
= HIWORD (msg
->msg
.lParam
);
3081 ScreenToClient (msg
->msg
.hwnd
, &p
);
3084 XSETINT (result
->x
, p
.x
);
3085 XSETINT (result
->y
, p
.y
);
3087 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
3090 for (i
= 0; i
< num_files
; i
++)
3092 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
3095 name
= alloca (len
+ 1);
3096 DragQueryFile (hdrop
, i
, name
, len
+ 1);
3097 files
= Fcons (DECODE_FILE (build_string (name
)), files
);
3102 XSETFRAME (frame
, f
);
3103 result
->frame_or_window
= frame
;
3104 result
->arg
= files
;
3109 /* Function to report a mouse movement to the mainstream Emacs code.
3110 The input handler calls this.
3112 We have received a mouse movement event, which is given in *event.
3113 If the mouse is over a different glyph than it was last time, tell
3114 the mainstream emacs code by setting mouse_moved. If not, ask for
3115 another motion event, so we can check again the next time it moves. */
3117 static MSG last_mouse_motion_event
;
3118 static Lisp_Object last_mouse_motion_frame
;
3121 note_mouse_movement (frame
, msg
)
3125 int mouse_x
= LOWORD (msg
->lParam
);
3126 int mouse_y
= HIWORD (msg
->lParam
);
3128 last_mouse_movement_time
= msg
->time
;
3129 memcpy (&last_mouse_motion_event
, msg
, sizeof (last_mouse_motion_event
));
3130 XSETFRAME (last_mouse_motion_frame
, frame
);
3132 if (!FRAME_X_OUTPUT (frame
))
3135 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
3137 frame
->mouse_moved
= 1;
3138 last_mouse_scroll_bar
= Qnil
;
3139 note_mouse_highlight (frame
, -1, -1);
3140 last_mouse_glyph_frame
= 0;
3144 /* Has the mouse moved off the glyph it was on at the last sighting? */
3145 if (frame
!= last_mouse_glyph_frame
3146 || mouse_x
< last_mouse_glyph
.left
3147 || mouse_x
>= last_mouse_glyph
.right
3148 || mouse_y
< last_mouse_glyph
.top
3149 || mouse_y
>= last_mouse_glyph
.bottom
)
3151 frame
->mouse_moved
= 1;
3152 last_mouse_scroll_bar
= Qnil
;
3153 note_mouse_highlight (frame
, mouse_x
, mouse_y
);
3154 /* Remember the mouse position here, as w32_mouse_position only
3155 gets called when mouse tracking is enabled but we also need
3156 to keep track of the mouse for help_echo and highlighting at
3158 remember_mouse_glyph (frame
, mouse_x
, mouse_y
, &last_mouse_glyph
);
3159 last_mouse_glyph_frame
= frame
;
3167 /************************************************************************
3169 ************************************************************************/
3171 static struct scroll_bar
*x_window_to_scroll_bar ();
3172 static void x_scroll_bar_report_motion ();
3173 static void x_check_fullscreen
P_ ((struct frame
*));
3176 redo_mouse_highlight ()
3178 if (!NILP (last_mouse_motion_frame
)
3179 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3180 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3181 LOWORD (last_mouse_motion_event
.lParam
),
3182 HIWORD (last_mouse_motion_event
.lParam
));
3186 w32_define_cursor (window
, cursor
)
3190 PostMessage (window
, WM_EMACS_SETCURSOR
, (WPARAM
) cursor
, 0);
3192 /* Return the current position of the mouse.
3193 *fp should be a frame which indicates which display to ask about.
3195 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3196 and *part to the frame, window, and scroll bar part that the mouse
3197 is over. Set *x and *y to the portion and whole of the mouse's
3198 position on the scroll bar.
3200 If the mouse movement started elsewhere, set *fp to the frame the
3201 mouse is on, *bar_window to nil, and *x and *y to the character cell
3204 Set *time to the server time-stamp for the time at which the mouse
3205 was at this position.
3207 Don't store anything if we don't have a valid set of values to report.
3209 This clears the mouse_moved flag, so we can wait for the next mouse
3213 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3216 Lisp_Object
*bar_window
;
3217 enum scroll_bar_part
*part
;
3219 unsigned long *time
;
3225 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3226 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3231 Lisp_Object frame
, tail
;
3233 /* Clear the mouse-moved flag for every frame on this display. */
3234 FOR_EACH_FRAME (tail
, frame
)
3235 XFRAME (frame
)->mouse_moved
= 0;
3237 last_mouse_scroll_bar
= Qnil
;
3241 /* Now we have a position on the root; find the innermost window
3242 containing the pointer. */
3244 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3245 && FRAME_LIVE_P (last_mouse_frame
))
3247 /* If mouse was grabbed on a frame, give coords for that frame
3248 even if the mouse is now outside it. */
3249 f1
= last_mouse_frame
;
3253 /* Is window under mouse one of our frames? */
3254 f1
= x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
),
3255 WindowFromPoint (pt
));
3258 /* If not, is it one of our scroll bars? */
3261 struct scroll_bar
*bar
3262 = x_window_to_scroll_bar (WindowFromPoint (pt
));
3266 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3270 if (f1
== 0 && insist
> 0)
3271 f1
= SELECTED_FRAME ();
3275 /* Ok, we found a frame. Store all the values.
3276 last_mouse_glyph is a rectangle used to reduce the
3277 generation of mouse events. To not miss any motion
3278 events, we must divide the frame into rectangles of the
3279 size of the smallest character that could be displayed
3280 on it, i.e. into the same rectangles that matrices on
3281 the frame are divided into. */
3283 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3284 remember_mouse_glyph (f1
, pt
.x
, pt
.y
, &last_mouse_glyph
);
3285 last_mouse_glyph_frame
= f1
;
3292 *time
= last_mouse_movement_time
;
3301 /***********************************************************************
3303 ***********************************************************************/
3305 /* Handle mouse button event on the tool-bar of frame F, at
3306 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3310 w32_handle_tool_bar_click (f
, button_event
)
3312 struct input_event
*button_event
;
3314 int x
= XFASTINT (button_event
->x
);
3315 int y
= XFASTINT (button_event
->y
);
3317 if (button_event
->modifiers
& down_modifier
)
3318 handle_tool_bar_click (f
, x
, y
, 1, 0);
3320 handle_tool_bar_click (f
, x
, y
, 0,
3321 button_event
->modifiers
& ~up_modifier
);
3326 /***********************************************************************
3328 ***********************************************************************/
3330 /* Scroll bar support. */
3332 /* Given a window ID, find the struct scroll_bar which manages it.
3333 This can be called in GC, so we have to make sure to strip off mark
3336 static struct scroll_bar
*
3337 x_window_to_scroll_bar (window_id
)
3342 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3344 Lisp_Object frame
, bar
, condemned
;
3346 frame
= XCAR (tail
);
3347 /* All elements of Vframe_list should be frames. */
3348 if (! FRAMEP (frame
))
3351 /* Scan this frame's scroll bar list for a scroll bar with the
3353 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3354 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3355 /* This trick allows us to search both the ordinary and
3356 condemned scroll bar lists with one loop. */
3357 ! NILP (bar
) || (bar
= condemned
,
3360 bar
= XSCROLL_BAR (bar
)->next
)
3361 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
3362 return XSCROLL_BAR (bar
);
3370 /* Set the thumb size and position of scroll bar BAR. We are currently
3371 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3374 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
)
3375 struct scroll_bar
*bar
;
3376 int portion
, position
, whole
;
3378 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3379 /* We use the whole scroll-bar height in the calculations below, to
3380 avoid strange effects like scrolling backwards when just clicking
3381 on the handle (without moving it). */
3382 double range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
))
3383 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3384 int sb_page
, sb_pos
;
3385 BOOL draggingp
= !NILP (bar
->dragging
) ? TRUE
: FALSE
;
3388 /* We used to change the nPage setting while dragging the handle,
3389 but that had very strange effects (such as scrolling backwards
3390 while dragging downwards).
3392 Now, we don't change the nPage setting while dragging unless we
3393 get near to the end of the buffer, in which case we often have to
3394 resize the handle to "go all the way". */
3400 si
.cbSize
= sizeof (si
);
3401 si
.fMask
= SIF_POS
| SIF_PAGE
;
3402 GetScrollInfo(w
, SB_CTL
, &si
);
3403 near_bottom_p
= si
.nPos
+ si
.nPage
>= range
;
3411 /* Position scroll bar at rock bottom if the bottom of the
3412 buffer is visible. This avoids shinking the thumb away
3413 to nothing if it is held at the bottom of the buffer. */
3414 if (position
+ portion
>= whole
&& !draggingp
)
3416 sb_page
= range
* (whole
- position
) / whole
;
3421 sb_pos
= position
* range
/ whole
;
3422 sb_page
= (min (portion
, (whole
- position
)) * range
) / whole
;
3431 sb_page
= max (sb_page
, VERTICAL_SCROLL_BAR_MIN_HANDLE
);
3435 si
.cbSize
= sizeof (si
);
3436 si
.fMask
= SIF_PAGE
| SIF_POS
;
3440 SetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
3446 /************************************************************************
3447 Scroll bars, general
3448 ************************************************************************/
3451 my_create_scrollbar (f
, bar
)
3453 struct scroll_bar
* bar
;
3455 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
3456 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
3460 /*#define ATTACH_THREADS*/
3463 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
3465 #ifndef ATTACH_THREADS
3466 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
3467 (WPARAM
) hwnd
, (LPARAM
) how
);
3469 return ShowWindow (hwnd
, how
);
3474 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
3475 int x
, int y
, int cx
, int cy
, UINT flags
)
3477 #ifndef ATTACH_THREADS
3479 pos
.hwndInsertAfter
= hwndAfter
;
3485 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
3487 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
3492 my_set_focus (f
, hwnd
)
3496 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
3501 my_set_foreground_window (hwnd
)
3504 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
3509 my_destroy_window (f
, hwnd
)
3513 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
3517 /* Create a scroll bar and return the scroll bar vector for it. W is
3518 the Emacs window on which to create the scroll bar. TOP, LEFT,
3519 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3522 static struct scroll_bar
*
3523 x_scroll_bar_create (w
, top
, left
, width
, height
)
3525 int top
, left
, width
, height
;
3527 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3530 struct scroll_bar
*bar
3531 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
3535 XSETWINDOW (bar
->window
, w
);
3536 XSETINT (bar
->top
, top
);
3537 XSETINT (bar
->left
, left
);
3538 XSETINT (bar
->width
, width
);
3539 XSETINT (bar
->height
, height
);
3540 XSETINT (bar
->start
, 0);
3541 XSETINT (bar
->end
, 0);
3542 bar
->dragging
= Qnil
;
3543 bar
->fringe_extended_p
= Qnil
;
3545 /* Requires geometry to be set before call to create the real window */
3547 hwnd
= my_create_scrollbar (f
, bar
);
3549 si
.cbSize
= sizeof (si
);
3552 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3553 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3557 SetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3559 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
3561 /* Add bar to its frame's list of scroll bars. */
3562 bar
->next
= FRAME_SCROLL_BARS (f
);
3564 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3565 if (! NILP (bar
->next
))
3566 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3574 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3578 x_scroll_bar_remove (bar
)
3579 struct scroll_bar
*bar
;
3581 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3585 /* Destroy the window. */
3586 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
3588 /* Disassociate this scroll bar from its window. */
3589 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3594 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3595 that we are displaying PORTION characters out of a total of WHOLE
3596 characters, starting at POSITION. If WINDOW has no scroll bar,
3599 w32_set_vertical_scroll_bar (w
, portion
, whole
, position
)
3601 int portion
, whole
, position
;
3603 struct frame
*f
= XFRAME (w
->frame
);
3604 struct scroll_bar
*bar
;
3605 int top
, height
, left
, sb_left
, width
, sb_width
;
3606 int window_y
, window_height
;
3607 int fringe_extended_p
;
3609 /* Get window dimensions. */
3610 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
3612 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
3613 height
= window_height
;
3615 /* Compute the left edge of the scroll bar area. */
3616 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
3618 /* Compute the width of the scroll bar which might be less than
3619 the width of the area reserved for the scroll bar. */
3620 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
3621 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
3625 /* Compute the left edge of the scroll bar. */
3626 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
3627 sb_left
= left
+ (WINDOW_RIGHTMOST_P (w
) ? width
- sb_width
: 0);
3629 sb_left
= left
+ (WINDOW_LEFTMOST_P (w
) ? 0 : width
- sb_width
);
3631 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
))
3632 fringe_extended_p
= (WINDOW_LEFTMOST_P (w
)
3633 && WINDOW_LEFT_FRINGE_WIDTH (w
)
3634 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
3635 || WINDOW_LEFT_MARGIN_COLS (w
) == 0));
3637 fringe_extended_p
= (WINDOW_RIGHTMOST_P (w
)
3638 && WINDOW_RIGHT_FRINGE_WIDTH (w
)
3639 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
3640 || WINDOW_RIGHT_MARGIN_COLS (w
) == 0));
3642 /* Does the scroll bar exist yet? */
3643 if (NILP (w
->vertical_scroll_bar
))
3647 if (width
> 0 && height
> 0)
3649 hdc
= get_frame_dc (f
);
3650 if (fringe_extended_p
)
3651 w32_clear_area (f
, hdc
, sb_left
, top
, sb_width
, height
);
3653 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
3654 release_frame_dc (f
, hdc
);
3658 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
3662 /* It may just need to be moved and resized. */
3665 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
3666 hwnd
= SCROLL_BAR_W32_WINDOW (bar
);
3668 /* If already correctly positioned, do nothing. */
3669 if ( XINT (bar
->left
) == sb_left
3670 && XINT (bar
->top
) == top
3671 && XINT (bar
->width
) == sb_width
3672 && XINT (bar
->height
) == height
3673 && !NILP (bar
->fringe_extended_p
) == fringe_extended_p
)
3675 /* Redraw after clear_frame. */
3676 if (!my_show_window (f
, hwnd
, SW_NORMAL
))
3677 InvalidateRect (hwnd
, NULL
, FALSE
);
3685 if (width
&& height
)
3687 hdc
= get_frame_dc (f
);
3688 /* Since Windows scroll bars are smaller than the space reserved
3689 for them on the frame, we have to clear "under" them. */
3690 if (fringe_extended_p
)
3691 w32_clear_area (f
, hdc
, sb_left
, top
, sb_width
, height
);
3693 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
3694 release_frame_dc (f
, hdc
);
3696 /* Make sure scroll bar is "visible" before moving, to ensure the
3697 area of the parent window now exposed will be refreshed. */
3698 my_show_window (f
, hwnd
, SW_HIDE
);
3699 MoveWindow (hwnd
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
3700 top
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
3701 max (height
, 1), TRUE
);
3703 si
.cbSize
= sizeof (si
);
3704 si
.fMask
= SIF_RANGE
;
3706 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3707 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3709 SetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3711 my_show_window (f
, hwnd
, SW_NORMAL
);
3712 /* InvalidateRect (w, NULL, FALSE); */
3714 /* Remember new settings. */
3715 XSETINT (bar
->left
, sb_left
);
3716 XSETINT (bar
->top
, top
);
3717 XSETINT (bar
->width
, sb_width
);
3718 XSETINT (bar
->height
, height
);
3723 bar
->fringe_extended_p
= fringe_extended_p
? Qt
: Qnil
;
3725 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
3727 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
3731 /* The following three hooks are used when we're doing a thorough
3732 redisplay of the frame. We don't explicitly know which scroll bars
3733 are going to be deleted, because keeping track of when windows go
3734 away is a real pain - "Can you say set-window-configuration, boys
3735 and girls?" Instead, we just assert at the beginning of redisplay
3736 that *all* scroll bars are to be removed, and then save a scroll bar
3737 from the fiery pit when we actually redisplay its window. */
3739 /* Arrange for all scroll bars on FRAME to be removed at the next call
3740 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3741 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3744 w32_condemn_scroll_bars (frame
)
3747 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3748 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3751 bar
= FRAME_SCROLL_BARS (frame
);
3752 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3753 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3754 XSCROLL_BAR (bar
)->prev
= Qnil
;
3755 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3756 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3757 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3762 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3763 Note that WINDOW isn't necessarily condemned at all. */
3766 w32_redeem_scroll_bar (window
)
3767 struct window
*window
;
3769 struct scroll_bar
*bar
;
3772 /* We can't redeem this window's scroll bar if it doesn't have one. */
3773 if (NILP (window
->vertical_scroll_bar
))
3776 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3778 /* Unlink it from the condemned list. */
3779 f
= XFRAME (WINDOW_FRAME (window
));
3780 if (NILP (bar
->prev
))
3782 /* If the prev pointer is nil, it must be the first in one of
3784 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3785 /* It's not condemned. Everything's fine. */
3787 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3788 window
->vertical_scroll_bar
))
3789 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3791 /* If its prev pointer is nil, it must be at the front of
3792 one or the other! */
3796 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3798 if (! NILP (bar
->next
))
3799 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3801 bar
->next
= FRAME_SCROLL_BARS (f
);
3803 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3804 if (! NILP (bar
->next
))
3805 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3808 /* Remove all scroll bars on FRAME that haven't been saved since the
3809 last call to `*condemn_scroll_bars_hook'. */
3812 w32_judge_scroll_bars (f
)
3815 Lisp_Object bar
, next
;
3817 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3819 /* Clear out the condemned list now so we won't try to process any
3820 more events on the hapless scroll bars. */
3821 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3823 for (; ! NILP (bar
); bar
= next
)
3825 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3827 x_scroll_bar_remove (b
);
3830 b
->next
= b
->prev
= Qnil
;
3833 /* Now there should be no references to the condemned scroll bars,
3834 and they should get garbage-collected. */
3837 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3838 is set to something other than NO_EVENT, it is enqueued.
3840 This may be called from a signal handler, so we have to ignore GC
3844 w32_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3845 struct scroll_bar
*bar
;
3847 struct input_event
*emacs_event
;
3849 if (! WINDOWP (bar
->window
))
3852 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
3853 emacs_event
->code
= 0;
3854 /* not really meaningful to distinguish up/down */
3855 emacs_event
->modifiers
= msg
->dwModifiers
;
3856 emacs_event
->frame_or_window
= bar
->window
;
3857 emacs_event
->arg
= Qnil
;
3858 emacs_event
->timestamp
= msg
->msg
.time
;
3861 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3863 int dragging
= !NILP (bar
->dragging
);
3866 si
.cbSize
= sizeof (si
);
3869 GetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3872 bar
->dragging
= Qnil
;
3875 last_mouse_scroll_bar_pos
= msg
->msg
.wParam
;
3877 switch (LOWORD (msg
->msg
.wParam
))
3880 emacs_event
->part
= scroll_bar_down_arrow
;
3883 emacs_event
->part
= scroll_bar_up_arrow
;
3886 emacs_event
->part
= scroll_bar_above_handle
;
3889 emacs_event
->part
= scroll_bar_below_handle
;
3892 emacs_event
->part
= scroll_bar_handle
;
3896 emacs_event
->part
= scroll_bar_handle
;
3900 case SB_THUMBPOSITION
:
3901 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
3902 y
= HIWORD (msg
->msg
.wParam
);
3904 emacs_event
->part
= scroll_bar_handle
;
3906 /* "Silently" update current position. */
3910 si
.cbSize
= sizeof (si
);
3913 /* Remember apparent position (we actually lag behind the real
3914 position, so don't set that directly. */
3915 last_scroll_bar_drag_pos
= y
;
3917 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3921 /* If this is the end of a drag sequence, then reset the scroll
3922 handle size to normal and do a final redraw. Otherwise do
3927 int start
= XINT (bar
->start
);
3928 int end
= XINT (bar
->end
);
3930 si
.cbSize
= sizeof (si
);
3931 si
.fMask
= SIF_PAGE
| SIF_POS
;
3932 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3933 si
.nPos
= last_scroll_bar_drag_pos
;
3934 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3938 emacs_event
->kind
= NO_EVENT
;
3942 XSETINT (emacs_event
->x
, y
);
3943 XSETINT (emacs_event
->y
, top_range
);
3949 /* Return information to the user about the current position of the mouse
3950 on the scroll bar. */
3953 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3955 Lisp_Object
*bar_window
;
3956 enum scroll_bar_part
*part
;
3958 unsigned long *time
;
3960 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3961 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3962 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3964 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3970 *bar_window
= bar
->window
;
3972 si
.cbSize
= sizeof (si
);
3973 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3975 GetScrollInfo (w
, SB_CTL
, &si
);
3977 top_range
= si
.nMax
- si
.nPage
+ 1;
3979 switch (LOWORD (last_mouse_scroll_bar_pos
))
3981 case SB_THUMBPOSITION
:
3983 *part
= scroll_bar_handle
;
3984 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
3985 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3988 *part
= scroll_bar_handle
;
3992 *part
= scroll_bar_handle
;
3997 XSETINT (*y
, top_range
);
4000 last_mouse_scroll_bar
= Qnil
;
4002 *time
= last_mouse_movement_time
;
4008 /* The screen has been cleared so we may have changed foreground or
4009 background colors, and the scroll bars may need to be redrawn.
4010 Clear out the scroll bars, and ask for expose events, so we can
4014 x_scroll_bar_clear (f
)
4019 /* We can have scroll bars even if this is 0,
4020 if we just turned off scroll bar mode.
4021 But in that case we should not clear them. */
4022 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4023 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
4024 bar
= XSCROLL_BAR (bar
)->next
)
4026 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
4027 HDC hdc
= GetDC (window
);
4030 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4031 arranges to refresh the scroll bar if hidden. */
4032 my_show_window (f
, window
, SW_HIDE
);
4034 GetClientRect (window
, &rect
);
4035 select_palette (f
, hdc
);
4036 w32_clear_rect (f
, hdc
, &rect
);
4037 deselect_palette (f
, hdc
);
4039 ReleaseDC (window
, hdc
);
4044 /* The main W32 event-reading loop - w32_read_socket. */
4046 /* Record the last 100 characters stored
4047 to help debug the loss-of-chars-during-GC problem. */
4049 static int temp_index
;
4050 static short temp_buffer
[100];
4052 /* Temporarily store lead byte of DBCS input sequences. */
4053 static char dbcs_lead
= 0;
4055 /* Read events coming from the W32 shell.
4056 This routine is called by the SIGIO handler.
4057 We return as soon as there are no more events to be read.
4059 We return the number of characters stored into the buffer,
4060 thus pretending to be `read'.
4062 EXPECTED is nonzero if the caller knows input is available.
4064 Some of these messages are reposted back to the message queue since the
4065 system calls the windows proc directly in a context where we cannot return
4066 the data nor can we guarantee the state we are in. So if we dispatch them
4067 we will get into an infinite loop. To prevent this from ever happening we
4068 will set a variable to indicate we are in the read_socket call and indicate
4069 which message we are processing since the windows proc gets called
4070 recursively with different messages by the system.
4074 w32_read_socket (sd
, expected
, hold_quit
)
4077 struct input_event
*hold_quit
;
4080 int check_visibility
= 0;
4083 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4085 if (interrupt_input_blocked
)
4087 interrupt_input_pending
= 1;
4091 interrupt_input_pending
= 0;
4094 /* So people can tell when we have read the available input. */
4095 input_signal_count
++;
4097 /* TODO: ghostscript integration. */
4098 while (get_next_msg (&msg
, FALSE
))
4100 struct input_event inev
;
4104 inev
.kind
= NO_EVENT
;
4107 switch (msg
.msg
.message
)
4109 case WM_EMACS_PAINT
:
4110 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4114 if (msg
.rect
.right
== msg
.rect
.left
||
4115 msg
.rect
.bottom
== msg
.rect
.top
)
4117 /* We may get paint messages even though the client
4118 area is clipped - these are not expose events. */
4119 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f
,
4122 else if (f
->async_visible
!= 1)
4124 /* Definitely not obscured, so mark as visible. */
4125 f
->async_visible
= 1;
4126 f
->async_iconified
= 0;
4127 SET_FRAME_GARBAGED (f
);
4128 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f
,
4131 /* WM_PAINT serves as MapNotify as well, so report
4132 visibility changes properly. */
4135 inev
.kind
= DEICONIFY_EVENT
;
4136 XSETFRAME (inev
.frame_or_window
, f
);
4138 else if (! NILP (Vframe_list
)
4139 && ! NILP (XCDR (Vframe_list
)))
4140 /* Force a redisplay sooner or later to update the
4141 frame titles in case this is the second frame. */
4142 record_asynch_buffer_change ();
4146 HDC hdc
= get_frame_dc (f
);
4148 /* Erase background again for safety. */
4149 w32_clear_rect (f
, hdc
, &msg
.rect
);
4150 release_frame_dc (f
, hdc
);
4154 msg
.rect
.right
- msg
.rect
.left
,
4155 msg
.rect
.bottom
- msg
.rect
.top
);
4160 case WM_INPUTLANGCHANGE
:
4161 /* Generate a language change event. */
4162 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4164 /* lParam contains the input lang ID. Use it to update our
4165 record of the keyboard codepage. */
4166 keyboard_codepage
= codepage_for_locale ((LCID
)(msg
.msg
.lParam
4171 inev
.kind
= LANGUAGE_CHANGE_EVENT
;
4172 XSETFRAME (inev
.frame_or_window
, f
);
4173 inev
.code
= msg
.msg
.wParam
;
4174 inev
.modifiers
= msg
.msg
.lParam
& 0xffff;
4180 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4182 if (f
&& !f
->iconified
)
4184 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
4185 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
4187 clear_mouse_face (dpyinfo
);
4188 dpyinfo
->mouse_face_hidden
= 1;
4191 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4193 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4194 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
4195 inev
.code
= msg
.msg
.wParam
;
4196 inev
.modifiers
= msg
.dwModifiers
;
4197 XSETFRAME (inev
.frame_or_window
, f
);
4198 inev
.timestamp
= msg
.msg
.time
;
4205 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4207 if (f
&& !f
->iconified
)
4209 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
4210 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
4212 clear_mouse_face (dpyinfo
);
4213 dpyinfo
->mouse_face_hidden
= 1;
4216 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4218 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4220 inev
.modifiers
= msg
.dwModifiers
;
4221 XSETFRAME (inev
.frame_or_window
, f
);
4222 inev
.timestamp
= msg
.msg
.time
;
4224 if (msg
.msg
.message
== WM_UNICHAR
)
4226 inev
.code
= msg
.msg
.wParam
;
4228 else if (msg
.msg
.wParam
< 256)
4233 dbcs
[1] = (char) msg
.msg
.wParam
;
4237 dbcs
[0] = dbcs_lead
;
4239 if (!MultiByteToWideChar (keyboard_codepage
, 0,
4243 DebPrint (("Invalid DBCS sequence: %d %d\n",
4245 inev
.kind
= NO_EVENT
;
4249 else if (IsDBCSLeadByteEx (keyboard_codepage
,
4250 (BYTE
) msg
.msg
.wParam
))
4252 dbcs_lead
= (char) msg
.msg
.wParam
;
4253 inev
.kind
= NO_EVENT
;
4258 if (!MultiByteToWideChar (keyboard_codepage
, 0,
4259 &dbcs
[1], 1, &code
, 1))
4261 /* What to do with garbage? */
4262 DebPrint (("Invalid character: %d\n", dbcs
[1]));
4263 inev
.kind
= NO_EVENT
;
4271 /* Windows shouldn't generate WM_CHAR events above 0xFF
4272 in non-Unicode message handlers. */
4273 DebPrint (("Non-byte WM_CHAR: %d\n", msg
.msg
.wParam
));
4274 inev
.kind
= NO_EVENT
;
4277 inev
.kind
= inev
.code
< 128 ? ASCII_KEYSTROKE_EVENT
4278 : MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
4283 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4285 if (f
&& !f
->iconified
)
4287 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
4288 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
4290 clear_mouse_face (dpyinfo
);
4291 dpyinfo
->mouse_face_hidden
= 1;
4294 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4296 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4297 inev
.kind
= MULTIMEDIA_KEY_EVENT
;
4298 inev
.code
= GET_APPCOMMAND_LPARAM(msg
.msg
.lParam
);
4299 inev
.modifiers
= msg
.dwModifiers
;
4300 XSETFRAME (inev
.frame_or_window
, f
);
4301 inev
.timestamp
= msg
.msg
.time
;
4306 /* Ignore non-movement. */
4308 int x
= LOWORD (msg
.msg
.lParam
);
4309 int y
= HIWORD (msg
.msg
.lParam
);
4310 if (x
== last_mousemove_x
&& y
== last_mousemove_y
)
4312 last_mousemove_x
= x
;
4313 last_mousemove_y
= y
;
4316 previous_help_echo_string
= help_echo_string
;
4317 help_echo_string
= Qnil
;
4319 if (dpyinfo
->grabbed
&& last_mouse_frame
4320 && FRAME_LIVE_P (last_mouse_frame
))
4321 f
= last_mouse_frame
;
4323 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4325 if (dpyinfo
->mouse_face_hidden
)
4327 dpyinfo
->mouse_face_hidden
= 0;
4328 clear_mouse_face (dpyinfo
);
4333 /* Generate SELECT_WINDOW_EVENTs when needed. */
4334 if (!NILP (Vmouse_autoselect_window
))
4337 int x
= LOWORD (msg
.msg
.lParam
);
4338 int y
= HIWORD (msg
.msg
.lParam
);
4340 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 0);
4342 /* Window will be selected only when it is not
4343 selected now and last mouse movement event was
4344 not in it. Minibuffer window will be selected
4345 only when it is active. */
4347 && !EQ (window
, last_window
)
4348 && !EQ (window
, selected_window
)
4349 /* For click-to-focus window managers
4350 create event iff we don't leave the
4352 && (focus_follows_mouse
4353 || (EQ (XWINDOW (window
)->frame
,
4354 XWINDOW (selected_window
)->frame
))))
4356 inev
.kind
= SELECT_WINDOW_EVENT
;
4357 inev
.frame_or_window
= window
;
4362 if (!note_mouse_movement (f
, &msg
.msg
))
4363 help_echo_string
= previous_help_echo_string
;
4367 /* If we move outside the frame, then we're
4368 certainly no longer on any text in the frame. */
4369 clear_mouse_face (dpyinfo
);
4372 /* If the contents of the global variable help_echo_string
4373 has changed, generate a HELP_EVENT. */
4374 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4375 But it was originally changed to this to fix a bug, so I have
4376 not removed it completely in case the bug is still there. */
4377 if (help_echo_string
!= previous_help_echo_string
||
4378 (!NILP (help_echo_string
) && !STRINGP (help_echo_string
) && f
->mouse_moved
))
4379 #else /* This is what xterm.c does. */
4380 if (!NILP (help_echo_string
)
4381 || !NILP (previous_help_echo_string
))
4386 case WM_LBUTTONDOWN
:
4388 case WM_MBUTTONDOWN
:
4390 case WM_RBUTTONDOWN
:
4392 case WM_XBUTTONDOWN
:
4395 /* If we decide we want to generate an event to be seen
4396 by the rest of Emacs, we put it here. */
4401 if (dpyinfo
->grabbed
&& last_mouse_frame
4402 && FRAME_LIVE_P (last_mouse_frame
))
4403 f
= last_mouse_frame
;
4405 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4409 construct_mouse_click (&inev
, &msg
, f
);
4411 /* Is this in the tool-bar? */
4412 if (WINDOWP (f
->tool_bar_window
)
4413 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
4416 int x
= XFASTINT (inev
.x
);
4417 int y
= XFASTINT (inev
.y
);
4419 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
4421 if (EQ (window
, f
->tool_bar_window
))
4423 w32_handle_tool_bar_click (f
, &inev
);
4429 || (dpyinfo
->w32_focus_frame
4430 && f
!= dpyinfo
->w32_focus_frame
))
4431 inev
.kind
= NO_EVENT
;
4434 parse_button (msg
.msg
.message
, HIWORD (msg
.msg
.wParam
),
4439 dpyinfo
->grabbed
&= ~ (1 << button
);
4443 dpyinfo
->grabbed
|= (1 << button
);
4444 last_mouse_frame
= f
;
4445 /* Ignore any mouse motion that happened
4446 before this event; any subsequent mouse-movement
4447 Emacs events should reflect only motion after
4453 last_tool_bar_item
= -1;
4459 case WM_MOUSEHWHEEL
:
4461 if (dpyinfo
->grabbed
&& last_mouse_frame
4462 && FRAME_LIVE_P (last_mouse_frame
))
4463 f
= last_mouse_frame
;
4465 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4470 if (!dpyinfo
->w32_focus_frame
4471 || f
== dpyinfo
->w32_focus_frame
)
4473 /* Emit an Emacs wheel-up/down event. */
4474 construct_mouse_wheel (&inev
, &msg
, f
);
4476 /* Ignore any mouse motion that happened before this
4477 event; any subsequent mouse-movement Emacs events
4478 should reflect only motion after the
4482 last_mouse_frame
= f
;
4483 last_tool_bar_item
= -1;
4488 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4491 construct_drag_n_drop (&inev
, &msg
, f
);
4496 struct scroll_bar
*bar
=
4497 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
4500 w32_scroll_bar_handle_click (bar
, &msg
, &inev
);
4504 case WM_WINDOWPOSCHANGED
:
4505 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4508 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
4509 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
4511 check_visibility
= 1;
4515 case WM_ACTIVATEAPP
:
4516 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4518 x_check_fullscreen (f
);
4519 check_visibility
= 1;
4523 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4525 if (f
&& !f
->async_iconified
)
4529 x_real_positions (f
, &x
, &y
);
4534 check_visibility
= 1;
4538 /* wParam non-zero means Window is about to be shown, 0 means
4539 about to be hidden. */
4540 /* Redo the mouse-highlight after the tooltip has gone. */
4541 if (!msg
.msg
.wParam
&& msg
.msg
.hwnd
== tip_window
)
4544 redo_mouse_highlight ();
4547 /* If window has been obscured or exposed by another window
4548 being maximised or minimised/restored, then recheck
4549 visibility of all frames. Direct changes to our own
4550 windows get handled by WM_SIZE. */
4552 if (msg
.msg
.lParam
!= 0)
4553 check_visibility
= 1;
4556 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4557 f
->async_visible
= msg
.msg
.wParam
;
4561 check_visibility
= 1;
4565 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4567 /* Inform lisp of whether frame has been iconified etc. */
4570 switch (msg
.msg
.wParam
)
4572 case SIZE_MINIMIZED
:
4573 f
->async_visible
= 0;
4574 f
->async_iconified
= 1;
4576 inev
.kind
= ICONIFY_EVENT
;
4577 XSETFRAME (inev
.frame_or_window
, f
);
4580 case SIZE_MAXIMIZED
:
4582 f
->async_visible
= 1;
4583 f
->async_iconified
= 0;
4585 /* wait_reading_process_output will notice this and update
4586 the frame's display structures. */
4587 SET_FRAME_GARBAGED (f
);
4593 /* Reset top and left positions of the Window
4594 here since Windows sends a WM_MOVE message
4595 BEFORE telling us the Window is minimized
4596 when the Window is iconified, with 3000,3000
4598 x_real_positions (f
, &x
, &y
);
4602 inev
.kind
= DEICONIFY_EVENT
;
4603 XSETFRAME (inev
.frame_or_window
, f
);
4605 else if (! NILP (Vframe_list
)
4606 && ! NILP (XCDR (Vframe_list
)))
4607 /* Force a redisplay sooner or later
4608 to update the frame titles
4609 in case this is the second frame. */
4610 record_asynch_buffer_change ();
4615 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
4623 GetClientRect (msg
.msg
.hwnd
, &rect
);
4625 height
= rect
.bottom
- rect
.top
;
4626 width
= rect
.right
- rect
.left
;
4628 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
4629 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
4631 /* TODO: Clip size to the screen dimensions. */
4633 /* Even if the number of character rows and columns has
4634 not changed, the font size may have changed, so we need
4635 to check the pixel dimensions as well. */
4637 if (columns
!= FRAME_COLS (f
)
4638 || rows
!= FRAME_LINES (f
)
4639 || width
!= FRAME_PIXEL_WIDTH (f
)
4640 || height
!= FRAME_PIXEL_HEIGHT (f
))
4642 change_frame_size (f
, rows
, columns
, 0, 1, 0);
4643 SET_FRAME_GARBAGED (f
);
4644 cancel_mouse_face (f
);
4645 FRAME_PIXEL_WIDTH (f
) = width
;
4646 FRAME_PIXEL_HEIGHT (f
) = height
;
4647 f
->win_gravity
= NorthWestGravity
;
4651 check_visibility
= 1;
4655 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4658 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4660 /* If we move outside the frame, then we're
4661 certainly no longer on any text in the frame. */
4662 clear_mouse_face (dpyinfo
);
4663 dpyinfo
->mouse_face_mouse_frame
= 0;
4666 /* Generate a nil HELP_EVENT to cancel a help-echo.
4667 Do it only if there's something to cancel.
4668 Otherwise, the startup message is cleared when
4669 the mouse leaves the frame. */
4670 if (any_help_event_p
)
4676 w32_detect_focus_change (dpyinfo
, &msg
, &inev
);
4678 dpyinfo
->grabbed
= 0;
4679 check_visibility
= 1;
4683 f
= x_top_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4687 if (f
== dpyinfo
->w32_focus_event_frame
)
4688 dpyinfo
->w32_focus_event_frame
= 0;
4690 if (f
== dpyinfo
->w32_focus_frame
)
4691 x_new_focus_frame (dpyinfo
, 0);
4693 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4695 /* If we move outside the frame, then we're
4696 certainly no longer on any text in the frame. */
4697 clear_mouse_face (dpyinfo
);
4698 dpyinfo
->mouse_face_mouse_frame
= 0;
4701 /* Generate a nil HELP_EVENT to cancel a help-echo.
4702 Do it only if there's something to cancel.
4703 Otherwise, the startup message is cleared when
4704 the mouse leaves the frame. */
4705 if (any_help_event_p
)
4709 dpyinfo
->grabbed
= 0;
4710 check_visibility
= 1;
4714 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4718 inev
.kind
= DELETE_WINDOW_EVENT
;
4719 XSETFRAME (inev
.frame_or_window
, f
);
4724 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4728 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
4729 XSETFRAME (inev
.frame_or_window
, f
);
4734 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4738 extern void menubar_selection_callback
4739 (FRAME_PTR f
, void * client_data
);
4740 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
4743 check_visibility
= 1;
4746 case WM_DISPLAYCHANGE
:
4747 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4751 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
4752 DebPrint (("display change: %d %d\n",
4753 (short) LOWORD (msg
.msg
.lParam
),
4754 (short) HIWORD (msg
.msg
.lParam
)));
4757 check_visibility
= 1;
4761 /* Check for messages registered at runtime. */
4762 if (msg
.msg
.message
== msh_mousewheel
)
4764 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4765 msg
.msg
.message
= WM_MOUSEWHEEL
;
4771 if (inev
.kind
!= NO_EVENT
)
4773 kbd_buffer_store_event_hold (&inev
, hold_quit
);
4778 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
4783 XSETFRAME (frame
, f
);
4789 if (NILP (help_echo_string
))
4791 help_echo_object
= help_echo_window
= Qnil
;
4795 any_help_event_p
= 1;
4796 gen_help_event (help_echo_string
, frame
, help_echo_window
,
4797 help_echo_object
, help_echo_pos
);
4801 help_echo_string
= Qnil
;
4802 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
4808 /* If the focus was just given to an autoraising frame,
4810 /* ??? This ought to be able to handle more than one such frame. */
4811 if (pending_autoraise_frame
)
4813 x_raise_frame (pending_autoraise_frame
);
4814 pending_autoraise_frame
= 0;
4817 /* Check which frames are still visisble, if we have enqueued any user
4818 events or been notified of events that may affect visibility. We
4819 do this here because there doesn't seem to be any direct
4820 notification from Windows that the visibility of a window has
4821 changed (at least, not in all cases). */
4822 if (count
> 0 || check_visibility
)
4824 Lisp_Object tail
, frame
;
4826 FOR_EACH_FRAME (tail
, frame
)
4828 FRAME_PTR f
= XFRAME (frame
);
4829 /* The tooltip has been drawn already. Avoid the
4830 SET_FRAME_GARBAGED below. */
4831 if (EQ (frame
, tip_frame
))
4834 /* Check "visible" frames and mark each as obscured or not.
4835 Note that async_visible is nonzero for unobscured and
4836 obscured frames, but zero for hidden and iconified frames. */
4837 if (FRAME_W32_P (f
) && f
->async_visible
)
4843 /* Query clipping rectangle for the entire window area
4844 (GetWindowDC), not just the client portion (GetDC).
4845 Otherwise, the scrollbars and menubar aren't counted as
4846 part of the visible area of the frame, and we may think
4847 the frame is obscured when really a scrollbar is still
4848 visible and gets WM_PAINT messages above. */
4849 hdc
= GetWindowDC (FRAME_W32_WINDOW (f
));
4850 GetClipBox (hdc
, &clipbox
);
4851 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
4854 if (clipbox
.right
== clipbox
.left
4855 || clipbox
.bottom
== clipbox
.top
)
4857 /* Frame has become completely obscured so mark as
4858 such (we do this by setting async_visible to 2 so
4859 that FRAME_VISIBLE_P is still true, but redisplay
4861 f
->async_visible
= 2;
4863 if (!FRAME_OBSCURED_P (f
))
4865 DebPrint (("frame %p (%s) obscured\n", f
,
4871 /* Frame is not obscured, so mark it as such. */
4872 f
->async_visible
= 1;
4874 if (FRAME_OBSCURED_P (f
))
4876 SET_FRAME_GARBAGED (f
);
4877 DebPrint (("obscured frame %p (%s) found to be visible\n", f
,
4880 /* Force a redisplay sooner or later. */
4881 record_asynch_buffer_change ();
4894 /***********************************************************************
4896 ***********************************************************************/
4898 /* Set clipping for output in glyph row ROW. W is the window in which
4899 we operate. GC is the graphics context to set clipping in.
4901 ROW may be a text row or, e.g., a mode line. Text rows must be
4902 clipped to the interior of the window dedicated to text display,
4903 mode lines must be clipped to the whole window. */
4906 w32_clip_to_row (w
, row
, area
, hdc
)
4908 struct glyph_row
*row
;
4912 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4914 int window_x
, window_y
, window_width
;
4916 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4918 clip_rect
.left
= window_x
;
4919 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4920 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4921 clip_rect
.right
= clip_rect
.left
+ window_width
;
4922 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4924 w32_set_clip_rectangle (hdc
, &clip_rect
);
4928 /* Draw a hollow box cursor on window W in glyph row ROW. */
4931 x_draw_hollow_cursor (w
, row
)
4933 struct glyph_row
*row
;
4935 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4939 struct glyph
*cursor_glyph
;
4940 HBRUSH hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
4942 /* Get the glyph the cursor is on. If we can't tell because
4943 the current matrix is invalid or such, give up. */
4944 cursor_glyph
= get_phys_cursor_glyph (w
);
4945 if (cursor_glyph
== NULL
)
4948 /* Compute frame-relative coordinates for phys cursor. */
4949 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &left
, &top
, &h
);
4952 rect
.bottom
= rect
.top
+ h
;
4953 rect
.right
= rect
.left
+ w
->phys_cursor_width
;
4955 hdc
= get_frame_dc (f
);
4956 /* Set clipping, draw the rectangle, and reset clipping again. */
4957 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
4958 FrameRect (hdc
, &rect
, hb
);
4960 w32_set_clip_rectangle (hdc
, NULL
);
4961 release_frame_dc (f
, hdc
);
4965 /* Draw a bar cursor on window W in glyph row ROW.
4967 Implementation note: One would like to draw a bar cursor with an
4968 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4969 Unfortunately, I didn't find a font yet that has this property set.
4973 x_draw_bar_cursor (w
, row
, width
, kind
)
4975 struct glyph_row
*row
;
4977 enum text_cursor_kinds kind
;
4979 struct frame
*f
= XFRAME (w
->frame
);
4980 struct glyph
*cursor_glyph
;
4982 /* If cursor is out of bounds, don't draw garbage. This can happen
4983 in mini-buffer windows when switching between echo area glyphs
4985 cursor_glyph
= get_phys_cursor_glyph (w
);
4986 if (cursor_glyph
== NULL
)
4989 /* If on an image, draw like a normal cursor. That's usually better
4990 visible than drawing a bar, esp. if the image is large so that
4991 the bar might not be in the window. */
4992 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4994 struct glyph_row
*row
;
4995 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4996 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5000 COLORREF cursor_color
= f
->output_data
.w32
->cursor_pixel
;
5001 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5005 /* If the glyph's background equals the color we normally draw
5006 the bar cursor in, the bar cursor in its normal color is
5007 invisible. Use the glyph's foreground color instead in this
5008 case, on the assumption that the glyph's colors are chosen so
5009 that the glyph is legible. */
5010 if (face
->background
== cursor_color
)
5011 cursor_color
= face
->foreground
;
5013 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5015 hdc
= get_frame_dc (f
);
5016 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
5018 if (kind
== BAR_CURSOR
)
5021 width
= FRAME_CURSOR_WIDTH (f
);
5022 width
= min (cursor_glyph
->pixel_width
, width
);
5024 w
->phys_cursor_width
= width
;
5026 w32_fill_area (f
, hdc
, cursor_color
, x
,
5027 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5028 width
, row
->height
);
5032 int dummy_x
, dummy_y
, dummy_h
;
5035 width
= row
->height
;
5037 width
= min (row
->height
, width
);
5039 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &dummy_x
,
5040 &dummy_y
, &dummy_h
);
5041 w32_fill_area (f
, hdc
, cursor_color
, x
,
5042 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5043 row
->height
- width
),
5044 w
->phys_cursor_width
, width
);
5047 w32_set_clip_rectangle (hdc
, NULL
);
5048 release_frame_dc (f
, hdc
);
5053 /* RIF: Define cursor CURSOR on frame F. */
5056 w32_define_frame_cursor (f
, cursor
)
5060 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
5064 /* RIF: Clear area on frame F. */
5067 w32_clear_frame_area (f
, x
, y
, width
, height
)
5069 int x
, y
, width
, height
;
5073 hdc
= get_frame_dc (f
);
5074 w32_clear_area (f
, hdc
, x
, y
, width
, height
);
5075 release_frame_dc (f
, hdc
);
5078 /* RIF: Draw or clear cursor on window W. */
5081 w32_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5083 struct glyph_row
*glyph_row
;
5085 int cursor_type
, cursor_width
;
5090 /* If the user wants to use the system caret, make sure our own
5091 cursor remains invisible. */
5092 if (w32_use_visible_system_caret
)
5094 /* Call to erase_phys_cursor here seems to use the
5095 wrong values of w->phys_cursor, as they have been
5096 overwritten before this function was called. */
5097 if (w
->phys_cursor_type
!= NO_CURSOR
)
5098 erase_phys_cursor (w
);
5100 cursor_type
= w
->phys_cursor_type
= NO_CURSOR
;
5101 w
->phys_cursor_width
= -1;
5105 w
->phys_cursor_type
= cursor_type
;
5108 w
->phys_cursor_on_p
= 1;
5110 /* If this is the active cursor, we need to track it with the
5111 system caret, so third party software like screen magnifiers
5112 and speech synthesizers can follow the cursor. */
5115 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5116 HWND hwnd
= FRAME_W32_WINDOW (f
);
5119 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5121 = (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
5122 + glyph_row
->ascent
- w
->phys_cursor_ascent
);
5124 PostMessage (hwnd
, WM_IME_STARTCOMPOSITION
, 0, 0);
5126 /* If the size of the active cursor changed, destroy the old
5128 if (w32_system_caret_hwnd
5129 && (w32_system_caret_height
!= w
->phys_cursor_height
))
5130 PostMessage (hwnd
, WM_EMACS_DESTROY_CARET
, 0, 0);
5132 w32_system_caret_height
= w
->phys_cursor_height
;
5134 /* Move the system caret. */
5135 PostMessage (hwnd
, WM_EMACS_TRACK_CARET
, 0, 0);
5138 if (glyph_row
->exact_window_width_line_p
5139 && (glyph_row
->reversed_p
5140 ? (w
->phys_cursor
.hpos
< 0)
5141 : (w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])))
5143 glyph_row
->cursor_in_fringe_p
= 1;
5144 draw_fringe_bitmap (w
, glyph_row
, glyph_row
->reversed_p
);
5148 switch (cursor_type
)
5150 case HOLLOW_BOX_CURSOR
:
5151 x_draw_hollow_cursor (w
, glyph_row
);
5154 case FILLED_BOX_CURSOR
:
5155 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5159 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5163 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5167 w
->phys_cursor_width
= 0;
5181 x_bitmap_icon (f
, icon
)
5186 HANDLE small_icon
= NULL
;
5188 if (FRAME_W32_WINDOW (f
) == 0)
5192 main_icon
= LoadIcon (hinst
, EMACS_CLASS
);
5193 else if (STRINGP (icon
))
5195 /* Load the main icon from the named file. */
5196 main_icon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5197 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5198 /* Try to load a small icon to go with it. */
5199 small_icon
= LoadImage (NULL
, (LPCSTR
) SDATA (icon
), IMAGE_ICON
,
5200 GetSystemMetrics (SM_CXSMICON
),
5201 GetSystemMetrics (SM_CYSMICON
),
5204 else if (SYMBOLP (icon
))
5208 if (EQ (icon
, intern ("application")))
5209 name
= (LPCTSTR
) IDI_APPLICATION
;
5210 else if (EQ (icon
, intern ("hand")))
5211 name
= (LPCTSTR
) IDI_HAND
;
5212 else if (EQ (icon
, intern ("question")))
5213 name
= (LPCTSTR
) IDI_QUESTION
;
5214 else if (EQ (icon
, intern ("exclamation")))
5215 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5216 else if (EQ (icon
, intern ("asterisk")))
5217 name
= (LPCTSTR
) IDI_ASTERISK
;
5218 else if (EQ (icon
, intern ("winlogo")))
5219 name
= (LPCTSTR
) IDI_WINLOGO
;
5223 main_icon
= LoadIcon (NULL
, name
);
5228 if (main_icon
== NULL
)
5231 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5232 (LPARAM
) main_icon
);
5234 /* If there is a small icon that goes with it, set that too. */
5236 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_SMALL
,
5237 (LPARAM
) small_icon
);
5243 /************************************************************************
5245 ************************************************************************/
5247 /* Display Error Handling functions not used on W32. Listing them here
5248 helps diff stay in step when comparing w32term.c with xterm.c.
5250 x_error_catcher (display, error)
5251 x_catch_errors (dpy)
5252 x_catch_errors_unwind (old_val)
5253 x_check_errors (dpy, format)
5254 x_fully_uncatch_errors ()
5255 x_catching_errors ()
5256 x_had_errors_p (dpy)
5257 x_clear_errors (dpy)
5258 x_uncatch_errors (dpy, count)
5260 x_connection_signal (signalnum)
5261 x_connection_closed (dpy, error_message)
5262 x_error_quitter (display, error)
5263 x_error_handler (display, error)
5264 x_io_error_quitter (display)
5269 /* Changing the font of the frame. */
5272 x_new_font (f
, font_object
, fontset
)
5274 Lisp_Object font_object
;
5277 struct font
*font
= XFONT_OBJECT (font_object
);
5280 fontset
= fontset_from_font (font_object
);
5281 FRAME_FONTSET (f
) = fontset
;
5282 if (FRAME_FONT (f
) == font
)
5283 /* This font is already set in frame F. There's nothing more to
5287 FRAME_FONT (f
) = font
;
5288 FRAME_BASELINE_OFFSET (f
) = font
->baseline_offset
;
5289 FRAME_COLUMN_WIDTH (f
) = font
->average_width
;
5290 FRAME_SPACE_WIDTH (f
) = font
->space_width
;
5291 FRAME_LINE_HEIGHT (f
) = font
->height
;
5293 compute_fringe_widths (f
, 1);
5295 /* Compute the scroll bar width in character columns. */
5296 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5298 int wid
= FRAME_COLUMN_WIDTH (f
);
5299 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5300 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
- 1) / wid
;
5304 int wid
= FRAME_COLUMN_WIDTH (f
);
5305 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5308 /* Now make the frame display the given font. */
5309 if (FRAME_X_WINDOW (f
) != 0)
5311 /* Don't change the size of a tip frame; there's no point in
5312 doing it because it's done in Fx_show_tip, and it leads to
5313 problems because the tip frame has no widget. */
5314 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5315 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5318 /* X version sets font of input methods here also. */
5324 /***********************************************************************
5325 TODO: W32 Input Methods
5326 ***********************************************************************/
5327 /* Listing missing functions from xterm.c helps diff stay in step.
5329 xim_destroy_callback (xim, client_data, call_data)
5330 xim_open_dpy (dpyinfo, resource_name)
5332 xim_instantiate_callback (display, client_data, call_data)
5333 xim_initialize (dpyinfo, resource_name)
5334 xim_close_dpy (dpyinfo)
5339 /* Calculate the absolute position in frame F
5340 from its current recorded position values and gravity. */
5343 x_calc_absolute_position (f
)
5346 int flags
= f
->size_hint_flags
;
5348 /* The sum of the widths of the frame's left and right borders, and
5349 the sum of the heights of the frame's top and bottom borders (in
5350 pixels) drawn by Windows. */
5351 unsigned int left_right_borders_width
, top_bottom_borders_height
;
5353 /* Try to get the actual values of these two variables. We compute
5354 the border width (height) by subtracting the width (height) of
5355 the frame's client area from the width (height) of the frame's
5357 WINDOWPLACEMENT wp
= { 0 };
5358 RECT client_rect
= { 0 };
5360 if (GetWindowPlacement (FRAME_W32_WINDOW (f
), &wp
)
5361 && GetClientRect (FRAME_W32_WINDOW (f
), &client_rect
))
5363 left_right_borders_width
=
5364 (wp
.rcNormalPosition
.right
- wp
.rcNormalPosition
.left
) -
5365 (client_rect
.right
- client_rect
.left
);
5367 top_bottom_borders_height
=
5368 (wp
.rcNormalPosition
.bottom
- wp
.rcNormalPosition
.top
) -
5369 (client_rect
.bottom
- client_rect
.top
);
5373 /* Use sensible default values. */
5374 left_right_borders_width
= 8;
5375 top_bottom_borders_height
= 32;
5378 /* Treat negative positions as relative to the rightmost bottommost
5379 position that fits on the screen. */
5380 if (flags
& XNegative
)
5381 f
->left_pos
= (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f
))
5382 - FRAME_PIXEL_WIDTH (f
)
5384 - (left_right_borders_width
- 1));
5386 if (flags
& YNegative
)
5387 f
->top_pos
= (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f
))
5388 - FRAME_PIXEL_HEIGHT (f
)
5390 - (top_bottom_borders_height
- 1));
5392 /* The left_pos and top_pos are now relative to the top and left
5393 screen edges, so the flags should correspond. */
5394 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5397 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5398 to really change the position, and 0 when calling from
5399 x_make_frame_visible (in that case, XOFF and YOFF are the current
5400 position values). It is -1 when calling from x_set_frame_parameters,
5401 which means, do adjust for borders but don't change the gravity. */
5404 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5406 register int xoff
, yoff
;
5409 int modified_top
, modified_left
;
5411 if (change_gravity
> 0)
5415 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5417 f
->size_hint_flags
|= XNegative
;
5419 f
->size_hint_flags
|= YNegative
;
5420 f
->win_gravity
= NorthWestGravity
;
5422 x_calc_absolute_position (f
);
5425 x_wm_set_size_hint (f
, (long) 0, 0);
5427 modified_left
= f
->left_pos
;
5428 modified_top
= f
->top_pos
;
5430 my_set_window_pos (FRAME_W32_WINDOW (f
),
5432 modified_left
, modified_top
,
5434 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5439 /* Check if we need to resize the frame due to a fullscreen request.
5440 If so needed, resize the frame. */
5442 x_check_fullscreen (f
)
5445 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
5447 int width
, height
, ign
;
5449 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5451 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
5453 /* We do not need to move the window, it shall be taken care of
5454 when setting WM manager hints. */
5455 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
5457 change_frame_size (f
, height
, width
, 0, 1, 0);
5458 SET_FRAME_GARBAGED (f
);
5459 cancel_mouse_face (f
);
5461 /* Wait for the change of frame size to occur */
5462 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
5467 /* Call this to change the size of frame F's x-window.
5468 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5469 for this size change and subsequent size changes.
5470 Otherwise we leave the window gravity unchanged. */
5473 x_set_window_size (f
, change_gravity
, cols
, rows
)
5478 int pixelwidth
, pixelheight
;
5482 check_frame_size (f
, &rows
, &cols
);
5483 f
->scroll_bar_actual_width
5484 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5486 compute_fringe_widths (f
, 0);
5488 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5489 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5491 f
->win_gravity
= NorthWestGravity
;
5492 x_wm_set_size_hint (f
, (long) 0, 0);
5497 rect
.left
= rect
.top
= 0;
5498 rect
.right
= pixelwidth
;
5499 rect
.bottom
= pixelheight
;
5501 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
5502 FRAME_EXTERNAL_MENU_BAR (f
));
5504 my_set_window_pos (FRAME_W32_WINDOW (f
),
5507 rect
.right
- rect
.left
,
5508 rect
.bottom
- rect
.top
,
5509 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5513 /* The following mirrors what is done in xterm.c. It appears to be
5514 for informing lisp of the new size immediately, while the actual
5515 resize will happen asynchronously. But on Windows, the menu bar
5516 automatically wraps when the frame is too narrow to contain it,
5517 and that causes any calculations made here to come out wrong. The
5518 end is some nasty buggy behavior, including the potential loss
5521 Disabling this code is either not sufficient to fix the problems
5522 completely, or it causes fresh problems, but at least it removes
5523 the most problematic symptom of the minibuffer becoming unusable.
5525 -----------------------------------------------------------------
5527 Now, strictly speaking, we can't be sure that this is accurate,
5528 but the window manager will get around to dealing with the size
5529 change request eventually, and we'll hear how it went when the
5530 ConfigureNotify event gets here.
5532 We could just not bother storing any of this information here,
5533 and let the ConfigureNotify event set everything up, but that
5534 might be kind of confusing to the Lisp code, since size changes
5535 wouldn't be reported in the frame parameters until some random
5536 point in the future when the ConfigureNotify event arrives.
5538 We pass 1 for DELAY since we can't run Lisp code inside of
5540 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5541 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5542 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5544 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5545 receive in the ConfigureNotify event; if we get what we asked
5546 for, then the event won't cause the screen to become garbaged, so
5547 we have to make sure to do it here. */
5548 SET_FRAME_GARBAGED (f
);
5550 /* If cursor was outside the new size, mark it as off. */
5551 mark_window_cursors_off (XWINDOW (f
->root_window
));
5553 /* Clear out any recollection of where the mouse highlighting was,
5554 since it might be in a place that's outside the new frame size.
5555 Actually checking whether it is outside is a pain in the neck,
5556 so don't try--just let the highlighting be done afresh with new size. */
5557 cancel_mouse_face (f
);
5563 /* Mouse warping. */
5565 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5568 x_set_mouse_position (f
, x
, y
)
5574 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5575 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5577 if (pix_x
< 0) pix_x
= 0;
5578 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5580 if (pix_y
< 0) pix_y
= 0;
5581 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5583 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5587 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5596 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
5597 pt
.x
= rect
.left
+ pix_x
;
5598 pt
.y
= rect
.top
+ pix_y
;
5599 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
5601 SetCursorPos (pt
.x
, pt
.y
);
5607 /* focus shifting, raising and lowering. */
5610 x_focus_on_frame (f
)
5613 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
5615 /* Give input focus to frame. */
5618 /* Try not to change its Z-order if possible. */
5619 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
5620 my_set_focus (f
, FRAME_W32_WINDOW (f
));
5623 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5633 /* Raise frame F. */
5640 /* Strictly speaking, raise-frame should only change the frame's Z
5641 order, leaving input focus unchanged. This is reasonable behavior
5642 on X where the usual policy is point-to-focus. However, this
5643 behavior would be very odd on Windows where the usual policy is
5646 On X, if the mouse happens to be over the raised frame, it gets
5647 input focus anyway (so the window with focus will never be
5648 completely obscured) - if not, then just moving the mouse over it
5649 is sufficient to give it focus. On Windows, the user must actually
5650 click on the frame (preferrably the title bar so as not to move
5651 point), which is more awkward. Also, no other Windows program
5652 raises a window to the top but leaves another window (possibly now
5653 completely obscured) with input focus.
5655 Because there is a system setting on Windows that allows the user
5656 to choose the point to focus policy, we make the strict semantics
5657 optional, but by default we grab focus when raising. */
5659 if (NILP (Vw32_grab_focus_on_raise
))
5661 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5662 not already the foreground application: the frame is raised
5663 above all other frames belonging to us, but not above the
5664 current top window. To achieve that, we have to resort to this
5665 more cumbersome method. */
5667 HDWP handle
= BeginDeferWindowPos (2);
5670 DeferWindowPos (handle
,
5671 FRAME_W32_WINDOW (f
),
5674 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5676 DeferWindowPos (handle
,
5677 GetForegroundWindow (),
5678 FRAME_W32_WINDOW (f
),
5680 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5682 EndDeferWindowPos (handle
);
5687 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5693 /* Lower frame F. */
5699 my_set_window_pos (FRAME_W32_WINDOW (f
),
5702 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5707 w32_frame_raise_lower (f
, raise_flag
)
5711 if (! FRAME_W32_P (f
))
5720 /* Change of visibility. */
5722 /* This tries to wait until the frame is really visible.
5723 However, if the window manager asks the user where to position
5724 the frame, this will return before the user finishes doing that.
5725 The frame will not actually be visible at that time,
5726 but it will become visible later when the window manager
5727 finishes with it. */
5730 x_make_frame_visible (f
)
5737 type
= x_icon_type (f
);
5739 x_bitmap_icon (f
, type
);
5741 if (! FRAME_VISIBLE_P (f
))
5743 /* We test FRAME_GARBAGED_P here to make sure we don't
5744 call x_set_offset a second time
5745 if we get to x_make_frame_visible a second time
5746 before the window gets really visible. */
5747 if (! FRAME_ICONIFIED_P (f
)
5748 && ! f
->output_data
.w32
->asked_for_visible
)
5753 /* Adjust vertical window position in order to avoid being
5754 covered by a task bar placed at the bottom of the desktop. */
5755 SystemParametersInfo(SPI_GETWORKAREA
, 0, &workarea_rect
, 0);
5756 GetWindowRect(FRAME_W32_WINDOW(f
), &window_rect
);
5757 if (window_rect
.bottom
> workarea_rect
.bottom
5758 && window_rect
.top
> workarea_rect
.top
)
5759 f
->top_pos
= max (window_rect
.top
5760 - window_rect
.bottom
+ workarea_rect
.bottom
,
5763 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5766 f
->output_data
.w32
->asked_for_visible
= 1;
5768 /* The first of these seems to give more expected behavior, but
5769 was added as a commented out line in Sept 1997, with the
5770 second version remaining uncommented. There may have been
5771 some problem with it that led to it not being enabled,
5772 so the old version remains commented out below in case we
5773 decide we need to go back to it [23.0.60 2008-06-09]. */
5774 my_show_window (f
, FRAME_W32_WINDOW (f
),
5775 f
->async_iconified
? SW_RESTORE
: SW_SHOW
);
5776 /* my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); */
5779 /* Synchronize to ensure Emacs knows the frame is visible
5780 before we do anything else. We do this loop with input not blocked
5781 so that incoming events are handled. */
5786 /* This must come after we set COUNT. */
5789 XSETFRAME (frame
, f
);
5791 /* Wait until the frame is visible. Process X events until a
5792 MapNotify event has been seen, or until we think we won't get a
5793 MapNotify at all.. */
5794 for (count
= input_signal_count
+ 10;
5795 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5797 /* Force processing of queued events. */
5798 /* TODO: x_sync equivalent? */
5800 /* Machines that do polling rather than SIGIO have been observed
5801 to go into a busy-wait here. So we'll fake an alarm signal
5802 to let the handler know that there's something to be read.
5803 We used to raise a real alarm, but it seems that the handler
5804 isn't always enabled here. This is probably a bug. */
5805 if (input_polling_used ())
5807 /* It could be confusing if a real alarm arrives while processing
5808 the fake one. Turn it off and let the handler reset it. */
5809 int old_poll_suppress_count
= poll_suppress_count
;
5810 poll_suppress_count
= 1;
5811 poll_for_input_1 ();
5812 poll_suppress_count
= old_poll_suppress_count
;
5815 FRAME_SAMPLE_VISIBILITY (f
);
5819 /* Change from mapped state to withdrawn state. */
5821 /* Make the frame visible (mapped and not iconified). */
5823 x_make_frame_invisible (f
)
5826 /* Don't keep the highlight on an invisible frame. */
5827 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5828 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5832 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
5834 /* We can't distinguish this from iconification
5835 just by the event that we get from the server.
5836 So we can't win using the usual strategy of letting
5837 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5838 and synchronize with the server to make sure we agree. */
5840 FRAME_ICONIFIED_P (f
) = 0;
5841 f
->async_visible
= 0;
5842 f
->async_iconified
= 0;
5847 /* Change window state from mapped to iconified. */
5855 /* Don't keep the highlight on an invisible frame. */
5856 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5857 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5859 if (f
->async_iconified
)
5864 type
= x_icon_type (f
);
5866 x_bitmap_icon (f
, type
);
5868 /* Simulate the user minimizing the frame. */
5869 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
5875 /* Free X resources of frame F. */
5878 x_free_frame_resources (f
)
5881 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5885 /* We must free faces before destroying windows because some
5886 font-driver (e.g. xft) access a window while finishing a
5888 if (FRAME_FACE_CACHE (f
))
5889 free_frame_faces (f
);
5891 if (FRAME_W32_WINDOW (f
))
5892 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
5894 free_frame_menubar (f
);
5896 unload_color (f
, FRAME_FOREGROUND_PIXEL (f
));
5897 unload_color (f
, FRAME_BACKGROUND_PIXEL (f
));
5898 unload_color (f
, f
->output_data
.w32
->cursor_pixel
);
5899 unload_color (f
, f
->output_data
.w32
->cursor_foreground_pixel
);
5900 unload_color (f
, f
->output_data
.w32
->border_pixel
);
5901 unload_color (f
, f
->output_data
.w32
->mouse_pixel
);
5902 if (f
->output_data
.w32
->white_relief
.allocated_p
)
5903 unload_color (f
, f
->output_data
.w32
->white_relief
.pixel
);
5904 if (f
->output_data
.w32
->black_relief
.allocated_p
)
5905 unload_color (f
, f
->output_data
.w32
->black_relief
.pixel
);
5907 if (FRAME_FACE_CACHE (f
))
5908 free_frame_faces (f
);
5910 xfree (f
->output_data
.w32
);
5911 f
->output_data
.w32
= NULL
;
5913 if (f
== dpyinfo
->w32_focus_frame
)
5914 dpyinfo
->w32_focus_frame
= 0;
5915 if (f
== dpyinfo
->w32_focus_event_frame
)
5916 dpyinfo
->w32_focus_event_frame
= 0;
5917 if (f
== dpyinfo
->x_highlight_frame
)
5918 dpyinfo
->x_highlight_frame
= 0;
5920 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5922 dpyinfo
->mouse_face_beg_row
5923 = dpyinfo
->mouse_face_beg_col
= -1;
5924 dpyinfo
->mouse_face_end_row
5925 = dpyinfo
->mouse_face_end_col
= -1;
5926 dpyinfo
->mouse_face_window
= Qnil
;
5927 dpyinfo
->mouse_face_deferred_gc
= 0;
5928 dpyinfo
->mouse_face_mouse_frame
= 0;
5935 /* Destroy the window of frame F. */
5937 x_destroy_window (f
)
5940 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5942 x_free_frame_resources (f
);
5943 dpyinfo
->reference_count
--;
5947 /* Setting window manager hints. */
5949 /* Set the normal size hints for the window manager, for frame F.
5950 FLAGS is the flags word to use--or 0 meaning preserve the flags
5951 that the window now has.
5952 If USER_POSITION is nonzero, we set the USPosition
5953 flag (this is useful when FLAGS is 0). */
5955 x_wm_set_size_hint (f
, flags
, user_position
)
5960 Window window
= FRAME_W32_WINDOW (f
);
5964 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
5965 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
5966 SetWindowLong (window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
5967 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
5972 /* Window manager things */
5974 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5979 Window window
= FRAME_W32_WINDOW (f
);
5981 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5982 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5983 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5985 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5990 /***********************************************************************
5992 ***********************************************************************/
5994 static int w32_initialized
= 0;
5997 w32_initialize_display_info (display_name
)
5998 Lisp_Object display_name
;
6000 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6002 bzero (dpyinfo
, sizeof (*dpyinfo
));
6004 /* Put it on w32_display_name_list. */
6005 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6006 w32_display_name_list
);
6007 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
6009 dpyinfo
->w32_id_name
6010 = (char *) xmalloc (SCHARS (Vinvocation_name
)
6011 + SCHARS (Vsystem_name
)
6013 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
6014 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
6016 /* Default Console mode values - overridden when running in GUI mode
6017 with values obtained from system metrics. */
6020 dpyinfo
->n_planes
= 1;
6021 dpyinfo
->n_cbits
= 4;
6022 dpyinfo
->n_fonts
= 0;
6023 dpyinfo
->smallest_font_height
= 1;
6024 dpyinfo
->smallest_char_width
= 1;
6026 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6027 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6028 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
6029 dpyinfo
->mouse_face_window
= Qnil
;
6030 dpyinfo
->mouse_face_overlay
= Qnil
;
6031 dpyinfo
->mouse_face_hidden
= 0;
6033 dpyinfo
->vertical_scroll_bar_cursor
= w32_load_cursor (IDC_ARROW
);
6034 /* TODO: dpyinfo->gray */
6038 /* Create an xrdb-style database of resources to supercede registry settings.
6039 The database is just a concatenation of C strings, finished by an additional
6040 \0. The strings are submitted to some basic normalization, so
6042 [ *]option[ *]:[ *]value...
6048 but any whitespace following value is not removed. */
6051 w32_make_rdb (xrm_option
)
6054 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
6055 char *current
= buffer
;
6058 int before_value
= 0;
6072 if (in_option
&& (ch
== ':'))
6077 else if (before_value
)
6082 else if (!(in_option
|| before_value
))
6094 x_flush (struct frame
* f
)
6095 { /* Nothing to do */ }
6098 extern frame_parm_handler w32_frame_parm_handlers
[];
6100 static struct redisplay_interface w32_redisplay_interface
=
6102 w32_frame_parm_handlers
,
6106 x_clear_end_of_line
,
6108 x_after_update_window_line
,
6109 x_update_window_begin
,
6110 x_update_window_end
,
6113 0, /* flush_display_optional */
6114 x_clear_window_mouse_face
,
6115 x_get_glyph_overhangs
,
6116 x_fix_overlapping_area
,
6117 w32_draw_fringe_bitmap
,
6118 w32_define_fringe_bitmap
,
6119 w32_destroy_fringe_bitmap
,
6120 w32_compute_glyph_string_overhangs
,
6121 x_draw_glyph_string
,
6122 w32_define_frame_cursor
,
6123 w32_clear_frame_area
,
6124 w32_draw_window_cursor
,
6125 w32_draw_vertical_window_border
,
6126 w32_shift_glyphs_for_insert
6129 static void x_delete_terminal (struct terminal
*term
);
6131 static struct terminal
*
6132 w32_create_terminal (struct w32_display_info
*dpyinfo
)
6134 struct terminal
*terminal
;
6136 terminal
= create_terminal ();
6138 terminal
->type
= output_w32
;
6139 terminal
->display_info
.w32
= dpyinfo
;
6140 dpyinfo
->terminal
= terminal
;
6142 /* MSVC does not type K&R functions with no arguments correctly, and
6143 so we must explicitly cast them. */
6144 terminal
->clear_frame_hook
= x_clear_frame
;
6145 terminal
->ins_del_lines_hook
= x_ins_del_lines
;
6146 terminal
->delete_glyphs_hook
= x_delete_glyphs
;
6147 terminal
->ring_bell_hook
= w32_ring_bell
;
6148 terminal
->reset_terminal_modes_hook
= w32_reset_terminal_modes
;
6149 terminal
->set_terminal_modes_hook
= w32_set_terminal_modes
;
6150 terminal
->update_begin_hook
= x_update_begin
;
6151 terminal
->update_end_hook
= x_update_end
;
6152 terminal
->set_terminal_window_hook
= w32_set_terminal_window
;
6153 terminal
->read_socket_hook
= w32_read_socket
;
6154 terminal
->frame_up_to_date_hook
= w32_frame_up_to_date
;
6155 terminal
->mouse_position_hook
= w32_mouse_position
;
6156 terminal
->frame_rehighlight_hook
= w32_frame_rehighlight
;
6157 terminal
->frame_raise_lower_hook
= w32_frame_raise_lower
;
6158 // terminal->fullscreen_hook = XTfullscreen_hook;
6159 terminal
->set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
6160 terminal
->condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
6161 terminal
->redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
6162 terminal
->judge_scroll_bars_hook
= w32_judge_scroll_bars
;
6164 terminal
->delete_frame_hook
= x_destroy_window
;
6165 terminal
->delete_terminal_hook
= x_delete_terminal
;
6167 terminal
->rif
= &w32_redisplay_interface
;
6168 terminal
->scroll_region_ok
= 1; /* We'll scroll partial frames. */
6169 terminal
->char_ins_del_ok
= 1;
6170 terminal
->line_ins_del_ok
= 1; /* We'll just blt 'em. */
6171 terminal
->fast_clear_end_of_line
= 1; /* X does this well. */
6172 terminal
->memory_below_frame
= 0; /* We don't remember what scrolls
6175 /* We don't yet support separate terminals on W32, so don't try to share
6176 keyboards between virtual terminals that are on the same physical
6177 terminal like X does. */
6178 terminal
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
6179 init_kboard (terminal
->kboard
);
6180 terminal
->kboard
->Vwindow_system
= intern ("w32");
6181 terminal
->kboard
->next_kboard
= all_kboards
;
6182 all_kboards
= terminal
->kboard
;
6183 /* Don't let the initial kboard remain current longer than necessary.
6184 That would cause problems if a file loaded on startup tries to
6185 prompt in the mini-buffer. */
6186 if (current_kboard
== initial_kboard
)
6187 current_kboard
= terminal
->kboard
;
6188 terminal
->kboard
->reference_count
++;
6194 x_delete_terminal (struct terminal
*terminal
)
6196 struct w32_display_info
*dpyinfo
= terminal
->display_info
.w32
;
6199 /* Protect against recursive calls. delete_frame in
6200 delete_terminal calls us back when it deletes our last frame. */
6201 if (!terminal
->name
)
6206 x_delete_display (dpyinfo
);
6210 struct w32_display_info
*
6211 w32_term_init (display_name
, xrm_option
, resource_name
)
6212 Lisp_Object display_name
;
6214 char *resource_name
;
6216 struct w32_display_info
*dpyinfo
;
6217 struct terminal
*terminal
;
6222 if (!w32_initialized
)
6225 w32_initialized
= 1;
6228 w32_initialize_display_info (display_name
);
6230 dpyinfo
= &one_w32_display_info
;
6231 terminal
= w32_create_terminal (dpyinfo
);
6233 /* Set the name of the terminal. */
6234 terminal
->name
= (char *) xmalloc (SBYTES (display_name
) + 1);
6235 strncpy (terminal
->name
, SDATA (display_name
), SBYTES (display_name
));
6236 terminal
->name
[SBYTES (display_name
)] = 0;
6238 dpyinfo
->xrdb
= xrm_option
? w32_make_rdb (xrm_option
) : NULL
;
6240 /* Put this display on the chain. */
6241 dpyinfo
->next
= x_display_list
;
6242 x_display_list
= dpyinfo
;
6246 dpyinfo
->root_window
= GetDesktopWindow ();
6247 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
6248 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
6249 dpyinfo
->resx
= GetDeviceCaps (hdc
, LOGPIXELSX
);
6250 dpyinfo
->resy
= GetDeviceCaps (hdc
, LOGPIXELSY
);
6251 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
6252 ReleaseDC (NULL
, hdc
);
6254 /* initialise palette with white and black */
6257 w32_defined_color (0, "white", &color
, 1);
6258 w32_defined_color (0, "black", &color
, 1);
6261 /* Add the default keyboard. */
6262 add_keyboard_wait_descriptor (0);
6264 /* Create Fringe Bitmaps and store them for later use.
6266 On W32, bitmaps are all unsigned short, as Windows requires
6267 bitmap data to be Word aligned. For some reason they are
6268 horizontally reflected compared to how they appear on X, so we
6269 need to bitswap and convert to unsigned shorts before creating
6271 w32_init_fringe (terminal
->rif
);
6274 fcntl (connection
, F_SETOWN
, getpid ());
6275 #endif /* ! defined (F_SETOWN) */
6278 if (interrupt_input
)
6279 init_sigio (connection
);
6280 #endif /* ! defined (SIGIO) */
6287 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6289 x_delete_display (dpyinfo
)
6290 struct w32_display_info
*dpyinfo
;
6292 /* Discard this display from w32_display_name_list and w32_display_list.
6293 We can't use Fdelq because that can quit. */
6294 if (! NILP (w32_display_name_list
)
6295 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
6296 w32_display_name_list
= XCDR (w32_display_name_list
);
6301 tail
= w32_display_name_list
;
6302 while (CONSP (tail
) && CONSP (XCDR (tail
)))
6304 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
6306 XSETCDR (tail
, XCDR (XCDR (tail
)));
6313 /* free palette table */
6315 struct w32_palette_entry
* plist
;
6317 plist
= dpyinfo
->color_list
;
6320 struct w32_palette_entry
* pentry
= plist
;
6321 plist
= plist
->next
;
6324 dpyinfo
->color_list
= NULL
;
6325 if (dpyinfo
->palette
)
6326 DeleteObject(dpyinfo
->palette
);
6328 xfree (dpyinfo
->w32_id_name
);
6330 w32_reset_fringes ();
6333 /* Set up use of W32. */
6335 DWORD WINAPI
w32_msg_worker (void * arg
);
6341 HRESULT (WINAPI
* set_user_model
) (wchar_t * id
);
6345 w32_system_caret_hwnd
= NULL
;
6346 w32_system_caret_height
= 0;
6347 w32_system_caret_x
= 0;
6348 w32_system_caret_y
= 0;
6350 /* On Windows 7 and later, we need to set the user model ID
6351 to associate emacsclient launched files with Emacs frames
6353 shell
= GetModuleHandle ("shell32.dll");
6357 = (void *) GetProcAddress (shell
,
6358 "SetCurrentProcessExplicitAppUserModelID");
6360 /* If the function is defined, then we are running on Windows 7
6361 or newer, and the UI uses this to group related windows
6362 together. Since emacs, runemacs, emacsclient are related, we
6363 want them grouped even though the executables are different,
6364 so we need to set a consistent ID between them. */
6366 set_user_model (L
"GNU.Emacs");
6369 /* Initialize w32_use_visible_system_caret based on whether a screen
6370 reader is in use. */
6371 if (!SystemParametersInfo (SPI_GETSCREENREADER
, 0,
6372 &w32_use_visible_system_caret
, 0))
6373 w32_use_visible_system_caret
= 0;
6375 last_tool_bar_item
= -1;
6376 any_help_event_p
= 0;
6378 /* Initialize input mode: interrupt_input off, no flow control, allow
6379 8 bit character input, standard quit char. */
6380 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
6383 DWORD input_locale_id
= (DWORD
) GetKeyboardLayout (0);
6384 keyboard_codepage
= codepage_for_locale ((LCID
) (input_locale_id
& 0xffff));
6387 /* Create the window thread - it will terminate itself when the app
6391 dwMainThreadId
= GetCurrentThreadId ();
6392 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6393 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
6395 /* Wait for thread to start */
6399 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
6401 hWindowsThread
= CreateThread (NULL
, 0,
6403 0, 0, &dwWindowsThreadId
);
6405 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6408 /* It is desirable that mainThread should have the same notion of
6409 focus window and active window as windowsThread. Unfortunately, the
6410 following call to AttachThreadInput, which should do precisely what
6411 we need, causes major problems when Emacs is linked as a console
6412 program. Unfortunately, we have good reasons for doing that, so
6413 instead we need to send messages to windowsThread to make some API
6414 calls for us (ones that affect, or depend on, the active/focus
6416 #ifdef ATTACH_THREADS
6417 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
6420 /* Dynamically link to optional system components. */
6422 HMODULE user_lib
= GetModuleHandle ("user32.dll");
6424 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6426 LOAD_PROC (user_lib
, SetLayeredWindowAttributes
);
6430 /* Ensure scrollbar handle is at least 5 pixels. */
6431 vertical_scroll_bar_min_handle
= 5;
6433 /* For either kind of scroll bar, take account of the arrows; these
6434 effectively form the border of the main scroll bar range. */
6435 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
6436 = GetSystemMetrics (SM_CYVSCROLL
);
6443 staticpro (&w32_display_name_list
);
6444 w32_display_name_list
= Qnil
;
6446 staticpro (&last_mouse_scroll_bar
);
6447 last_mouse_scroll_bar
= Qnil
;
6449 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
6451 DEFVAR_INT ("w32-num-mouse-buttons",
6452 &w32_num_mouse_buttons
,
6453 doc
: /* Number of physical mouse buttons. */);
6454 w32_num_mouse_buttons
= 2;
6456 DEFVAR_LISP ("w32-swap-mouse-buttons",
6457 &Vw32_swap_mouse_buttons
,
6458 doc
: /* Swap the mapping of middle and right mouse buttons.
6459 When nil, middle button is mouse-2 and right button is mouse-3. */);
6460 Vw32_swap_mouse_buttons
= Qnil
;
6462 DEFVAR_LISP ("w32-grab-focus-on-raise",
6463 &Vw32_grab_focus_on_raise
,
6464 doc
: /* Raised frame grabs input focus.
6465 When t, `raise-frame' grabs input focus as well. This fits well
6466 with the normal Windows click-to-focus policy, but might not be
6467 desirable when using a point-to-focus policy. */);
6468 Vw32_grab_focus_on_raise
= Qt
;
6470 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6471 &Vw32_capslock_is_shiftlock
,
6472 doc
: /* Apply CapsLock state to non character input keys.
6473 When nil, CapsLock only affects normal character input keys. */);
6474 Vw32_capslock_is_shiftlock
= Qnil
;
6476 DEFVAR_LISP ("w32-recognize-altgr",
6477 &Vw32_recognize_altgr
,
6478 doc
: /* Recognize right-alt and left-ctrl as AltGr.
6479 When nil, the right-alt and left-ctrl key combination is
6480 interpreted normally. */);
6481 Vw32_recognize_altgr
= Qt
;
6483 DEFVAR_BOOL ("w32-use-visible-system-caret",
6484 &w32_use_visible_system_caret
,
6485 doc
: /* Flag to make the system caret visible.
6486 When this is non-nil, Emacs will indicate the position of point by
6487 using the system caret instead of drawing its own cursor. Some screen
6488 reader software does not track the system cursor properly when it is
6489 invisible, and gets confused by Emacs drawing its own cursor, so this
6490 variable is initialized to t when Emacs detects that screen reader
6491 software is running as it starts up.
6493 When this variable is set, other variables affecting the appearance of
6494 the cursor have no effect. */);
6496 w32_use_visible_system_caret
= 0;
6498 /* We don't yet support this, but defining this here avoids whining
6499 from cus-start.el and other places, like "M-x set-variable". */
6500 DEFVAR_BOOL ("x-use-underline-position-properties",
6501 &x_use_underline_position_properties
,
6502 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
6503 A value of nil means ignore them. If you encounter fonts with bogus
6504 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6505 to 4.1, set this to nil. */);
6506 x_use_underline_position_properties
= 0;
6508 DEFVAR_BOOL ("x-underline-at-descent-line",
6509 &x_underline_at_descent_line
,
6510 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
6511 A value of nil means to draw the underline according to the value of the
6512 variable `x-use-underline-position-properties', which is usually at the
6513 baseline level. The default value is nil. */);
6514 x_underline_at_descent_line
= 0;
6516 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
6517 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
6518 Vx_toolkit_scroll_bars
= Qt
;
6520 staticpro (&last_mouse_motion_frame
);
6521 last_mouse_motion_frame
= Qnil
;
6524 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6525 (do not change this comment) */