aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32term.c
diff options
context:
space:
mode:
authorMartin Rudalics2014-07-27 15:21:30 +0200
committerMartin Rudalics2014-07-27 15:21:30 +0200
commit3477e27021dbe9366c3c1aaba80feb72f1138b29 (patch)
treec1ebfb6695e8d7f90ddad1a5bfaaf353be677514 /src/w32term.c
parent11fb71017b03f01a7e9e2db24973e756a41e16ec (diff)
downloademacs-3477e27021dbe9366c3c1aaba80feb72f1138b29.tar.gz
emacs-3477e27021dbe9366c3c1aaba80feb72f1138b29.zip
Complete pixelwise frame/window resizing, add horizontal scrollbar support.
* frame.el (frame-notice-user-settings): Rewrite using frame-initial-frame-tool-bar-height. * menu-bar.el (menu-bar-horizontal-scroll-bar) (menu-bar-no-horizontal-scroll-bar): New functions. (menu-bar-showhide-scroll-bar-menu): Add bindings for horizontal scroll bars. * scroll-bar.el (scroll-bar-lines) (set-horizontal-scroll-bar-mode) (get-horizontal-scroll-bar-mode, horizontal-scroll-bar-mode) (scroll-bar-horizontal-drag-1, scroll-bar-horizontal-drag) (scroll-bar-toolkit-horizontal-scroll): New functions. (horizontal-scroll-bar-mode) (previous-horizontal-scroll-bar-mode) (horizontal-scroll-bar-mode-explicit): New variables. (horizontal-scroll-bar-mode): New option. (toggle-horizontal-scroll-bar): Do something. (top-level): Bind horizontal-scroll-bar mouse-1. * startup.el (tool-bar-originally-present): Remove variable. (command-line): Don't set tool-bar-originally-present. * window.el (window-min-height): Update doc-string. (window--dump-frame): Dump horizontal scroll bar values. (window--min-size-1): Handle minibuffer window separately. Count in margins and horizontal scroll bar. Return safe value iff IGNORE equals 'safe. (frame-windows-min-size): New function (used by frame resizing routines). (fit-frame-to-buffer, fit-window-to-buffer): Count in horizontal scroll bars. (window--sanitize-window-sizes): New function. (window-split-min-size): Remove. (split-window): Count divider-width. Don't use `window-split-min-size' any more. Reword error messages. Sanitize windows sizes after splitting. * buffer.h (struct buffer): New fields scroll_bar_height and horizontal_scroll_bar_type. * buffer.c (bset_scroll_bar_height) (bset_horizontal_scroll_bar_type): New functions. (Fbuffer_swap_text): Handle old_pointm field. (init_buffer_once): Set defaults for scroll_bar_height and horizontal_scroll_bar_type. (syms_of_buffer): New variables scroll_bar_height and horizontal_scroll_bar_type. * dispextern.h (window_part): Rename ON_SCROLL_BAR to ON_VERTICAL_SCROLL_BAR. Add ON_HORIZONTAL_SCROLL_BAR. (set_vertical_scroll_bar): Remove prototype. (x_change_tool_bar_height): Add prototype. * dispnew.c (adjust_frame_glyphs_for_frame_redisplay) (window_to_frame_vpos, update_frame_1, scrolling, init_display): Use FRAME_TOTAL_COLS and FRAME_TOTAL_LINES instead of FRAME_COLS and FRAME_LINES. (adjust_frame_glyphs_for_window_redisplay): Rearrange lines. (update_window): Start mode_line_row->y after horizontal scroll bar. (change_frame_size_1): Call adjust_frame_size. (init_display): When changing the size of a tty frame do not pass height of menu bar. (Qframe_windows_min_size): New symbol. * frame.h (struct frame): List tool bar fields after menu bar fields. Add official, total_lines, horizontal_scroll_bars, config_scroll_bar_height and config_scroll_bar_lines fields. (FRAME_HAS_HORIZONTAL_SCROLL_BARS) (FRAME_CONFIG_SCROLL_BAR_HEIGHT, FRAME_CONFIG_SCROLL_BAR_LINES) (FRAME_SCROLL_BAR_AREA_HEIGHT, FRAME_SCROLL_BAR_COLS) (FRAME_SCROLL_BAR_LINES, FRAME_TOTAL_LINES, SET_FRAME_LINES) (FRAME_WINDOWS_HEIGHT): New macros. (SET_FRAME_HEIGHT, FRAME_TEXT_LINES_TO_PIXEL_HEIGHT) (FRAME_PIXEL_Y_TO_LINE, FRAME_PIXEL_HEIGHT_TO_TEXT_LINES) (FRAME_TEXT_TO_PIXEL_HEIGHT): Separately count top margin and horizontal scroll bar. (frame_inhibit_resize, adjust_frame_size) (frame_windows_min_size): Add declarations. (Qscroll_bar_height, Qhorizontal_scroll_bars) (x_set_scroll_bar_default_height, x_set_left_fringe) (x_set_right_fringe, x_set_vertical_scroll_bars) (x_set_horizontal_scroll_bars, x_set_scroll_bar_width) (x_set_scroll_bar_height): Add external declarations. * frame.c: (frame_inhibit_resize, frame_windows_min_size) (adjust_frame_size): New functions. (make_frame): Initial horizontal_scroll_bars field. Use SET_FRAME_LINES. Don't allow horizontal scroll bar in minibuffer window. (make_initial_frame, make_terminal_frame): No horizontal scroll bar in initial and terminal frames. Use adjust_frame_size. (Fframe_total_cols): Fix doc-string. (Fframe_total_lines, Fscroll_bar_height): New Lisp functions. (Fset_frame_height, Fset_frame_width, Fset_frame_size): Rewrite using adjust_frame_size. (Qscroll_bar_height, Qhorizontal_scroll_bars) (Qframe_windows_min_size): New symbols. (x_set_frame_parameters): Remove call of check_frame_size. (x_report_frame_params): Return scroll_bar_height value. (x_set_left_fringe, x_set_right_fringe): New functions. (adjust_frame_height, x_set_internal_border_width) (x_set_fringe_width): Remove. (x_set_internal_border_width, x_set_vertical_scroll_bars) (x_set_scroll_bar_width, x_set_right_divider_width) (x_set_bottom_divider_width): Rewrite using adjust_frame_size. (x_set_horizontal_scroll_bars, x_set_scroll_bar_height): New functions. (x_figure_window_size): Rewrite to make frame display the expected number of lines. (Vdefault_frame_scroll_bars): Rewrite doc-string. (Vdefault_frame_horizontal_scroll_bars) (Vframe_initial_frame_tool_bar_height) (frame_inhibit_implied_resize): New variables. * fringe.c (compute_fringe_widths): Remove. * gtkutil.h (YG_SB_MIN, YG_SB_MAX, YG_SB_RANGE): Define. (xg_create_horizontal_scroll_bar) (xg_update_horizontal_scrollbar_pos) (xg_set_toolkit_horizontal_scroll_bar_thumb) (xg_get_default_scrollbar_height) (xg_clear_under_internal_border): Extern. * gtkutil.c (xg_frame_resized): Don't call do_pending_window_change. (xg_frame_set_char_size): Use adjust_frame_size. (style_changed_cb): Call update_theme_scrollbar_height and x_set_scroll_bar_default_height. (x_wm_set_size_hint): Don't call check_frame_size. (update_theme_scrollbar_height) (xg_get_default_scrollbar_height) (xg_create_horizontal_scroll_bar) (xg_update_horizontal_scrollbar_pos) (xg_set_toolkit_horizontal_scroll_bar_thumb): New functions. (xg_create_scroll_bar): Set horizontal slot of bar. (xg_initialize): Call update_theme_scrollbar_height. (xg_clear_under_internal_border): No more static. * insdel.c (adjust_suspend_auto_hscroll): New function. (adjust_markers_for_delete, adjust_markers_for_insert) (adjust_markers_for_replace): Call adjust_suspend_auto_hscroll. * keyboard.c (readable_events, discard_mouse_events) (make_lispy_event): Handle horizontal scroll bar click events. (Fsuspend_emacs): When changing the size of a tty frame do not pass height of menu bar. (Qbefore_handle, Qhorizontal_handle, Qafter_handle, Qleft) (Qright, Qleftmost, Qrightmost): New symbols. * menu.c (Fx_popup_dialog): Use FRAME_TOTAL_LINES instead of FRAME_LINES. * minibuf.c (read_minibuf): Initialize suspend_auto_hscroll. * nsfns.m (x_set_internal_border_width): New function. * nsterm.m (ns_draw_fringe_bitmap, ns_set_vertical_scroll_bar): Remove extended fringe code. (x_set_window_size, x_new_font): Don't call compute_fringe_widths. * term.c (Fresume_tty): When changing the size of a tty frame do not pass height of menu bar. (clear_tty_hooks, set_tty_hooks): Clear horizontal_scroll_bar_hook. (init_tty): Frame has no horizontal scroll bars. * termhooks.h (enum scroll_bar_part): Add scroll_bar_move_ratio, scroll_bar_before_handle, scroll_bar_horizontal_handle, scroll_bar_after_handle, scroll_bar_left_arrow, scroll_bar_right_arrow, scroll_bar_to_leftmost and scroll_bar_to_rightmost entries. (enum event_kind): Add HORIZONTAL_SCROLL_BAR_CLICK_EVENT (struct terminal): Add set_horizontal_scroll_bar_hook. * w32console.c (initialize_w32_display): Clear horizontal_scroll_bar_hook. * w32fns.c (x_set_mouse_color): Use FRAME_W32_DISPLAY instead of FRAME_X_DISPLAY. (x_clear_under_internal_border, x_set_internal_border_width): New functions. (x_set_menu_bar_lines): Rewrite using frame_inhibit_resize. Set windows_or_buffers_changed when adding the menu bar. (x_set_tool_bar_lines): Rewrite using adjust_frame_size. (x_change_tool_bar_height, x_set_scroll_bar_default_height) (w32_createhscrollbar): New functions. (w32_createscrollbar): Rename to w32_createvscrollbar. (w32_createwindow): Init WND_HSCROLLBAR_INDEX. (w32_name_of_message): Replace WM_EMACS_CREATESCROLLBAR by WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR. Add WM_EMACS_SHOWCURSOR. (w32_wnd_proc): Handle WM_HSCROLL case. In WM_WINDOWPOSCHANGING case do not artificially impose WM size hints. Handle WM_EMACS_SHOWCURSOR case. Replace WM_EMACS_CREATESCROLLBAR case by WM_EMACS_CREATEVSCROLLBAR and WM_EMACS_CREATEHSCROLLBAR cases. (my_create_tip_window): Replace WND_SCROLLBAR_INDEX by WND_VSCROLLBAR_INDEX and WND_HSCROLLBAR_INDEX. (unwind_create_frame_1): Remove. (Fx_create_frame): Make both scrollbars the system standard width and height. Use official field of frame structure to inhibit running window-configuration-change-hook. (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size pixelwise. Handle frame's official field. (w32_frame_parm_handlers): Remove x_set_fringe_width entries. Add x_set_scroll_bar_height, x_set_horizontal_scroll_bars, x_set_left_fringe and x_set_right_fringe. * w32inevt.c (resize_event, maybe_generate_resize_event): Do not pass height of menu bar to change_frame_size. * w32menu.c (set_frame_menubar): Rewrite using frame_inhibit_resize. * w32term.h (struct w32_display_info): Add horizontal_scroll_bar_cursor and cursor_display_counter. (struct scroll_bar): Add horizontal. (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT) (HORIZONTAL_SCROLL_BAR_LEFT_RANGE) (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH) (HORIZONTAL_SCROLL_BAR_LEFT_BORDER) (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER) (HORIZONTAL_SCROLL_BAR_TOP_BORDER) (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): New macros. (WM_EMACS_CREATEVSCROLLBAR, WM_EMACS_CREATEHSCROLLBAR): Define instead of WM_EMACS_CREATESCROLLBAR. (WND_VSCROLLBAR_INDEX, WND_HSCROLLBAR_INDEX): Define instead of WND_SCROLLBAR_INDEX. * w32term.c (horizontal_scroll_bar_min_handle) (horizontal_scroll_bar_left_border) (horizontal_scroll_bar_right_border): New integers. (x_set_frame_alpha): Replace x_highlight_frame by w32_focus_frame. (x_window_to_scroll_bar): New argument "type". Update callers accordingly. (w32_set_horizontal_scroll_bar_thumb) (x_horizontal_scroll_bar_report_motion) (w32_set_horizontal_scroll_bar) (w32_horizontal_scroll_bar_handle_click) (x_horizontal_scroll_bar_report_motion): New functions. (w32_mouse_position): Discriminate horizontal and vertical scrollbar cases. (my_create_scrollbar): Replace with two new functions my_create_vscrollbar and my_create_hscrollbar. (x_scroll_bar_create): New argument "horizontal". Update callers accordingly. (x_scroll_bar_remove, w32_condemn_scroll_bars) (w32_redeem_scroll_bar, x_scroll_bar_clear): Handle horizontal scroll bar case. (w32_read_socket): Handle WM_HSCROLL cae. (x_new_font): Don't recompute fringe widths. Use frame_inhibit_resize. Calculate new menu bar height iff we build without toolkit. Always clear under internal border. (x_set_window_size): Don't check frame size or recompute fringes. Reset fullscreen status before applying sizes. Always resize as requested by pixelwise argument. Don't call do_pending_window_change. (x_wm_set_size_hint): Add call for FRAME_SCROLL_BAR_AREA_HEIGHT. (w32_initialize_display_info): Initialize dpyinfo's horizontal_scroll_bar_cursor entry. (w32_create_terminal): Add set_horizontal_scroll_bar_hook. (w32_initialize): Init horizontal_scroll_bar_min_handle and horizontal_scroll_bar_left_border. (w32fullscreen_hook): Intermittently resize window to normal when switching from fullscreen to maximized state. (run_window_configuration_change_hook): Don't run it if frame is not official yet. (unwind_change_frame): Remove. (Fset_window_configuration): Rewrite using frame's official field. * widget.c (set_frame_size): Don't call compute_fringe_widths. (EmacsFrameSetCharSize): Obey frame_inhibit_resize. * window.h (struct window): New fields old_pointm, horizontal_scroll_bar, horizontal_scroll_bar_type, hscroll_whole, scroll_bar_height and suspend_auto_hscroll. (wset_horizontal_scroll_bar, wset_horizontal_scroll_bar_type): New functions. (sanitize_window_sizes): Extern. (MINI_NON_ONLY_WINDOW_P, MINI_ONLY_WINDOW_P, WINDOW_PSEUDO_P) (WINDOW_TOPMOST_P, WINDOW_HAS_HORIZONTAL_SCROLL_BAR) (WINDOW_CONFIG_SCROLL_BAR_HEIGHT) (WINDOW_CONFIG_SCROLL_BAR_LINES) (WINDOW_SCROLL_BAR_LINES, WINDOW_SCROLL_BAR_AREA_HEIGHT): New macros. (WINDOW_LEFT_FRINGE_COLS, WINDOW_RIGHT_FRINGE_COLS) (WINDOW_FRINGE_COLS, WINDOW_FRINGE_EXTENDED_P): Remove macros. (WINDOW_VERTICAL_SCROLL_BAR_TYPE) (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT) (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT) (WINDOW_HAS_VERTICAL_SCROLL_BAR): Minor rewrite. (WINDOW_BOX_HEIGHT_NO_MODE_LINE, WINDOW_BOX_TEXT_HEIGHT) (WINDOW_SCROLL_BAR_AREA_Y): Count in scroll bar height. * window.c (wset_old_pointm, Fwindow_scroll_bar_height) (Fwindow_old_point, sanitize_window_sizes): New functions. (Qwindow_sanitize_window_sizes): New symbol. (window_body_height): Count in horizontal scroll bar. (set_window_hscroll, Fscroll_left, Fscroll_right): Set suspend_auto_hscroll slot. (Fwindow_inside_edges): Count fringes pixelwise. (coordinates_in_window, Fcoordinates_in_window_p): Consider horizontal scroll bar. (check_frame_size, adjust_window_margins): Remove functions and corresponding calls. (set_window_buffer): Initialize old_pointm and horizontal scroll bars. (temp_output_buffer_show): Reset hscroll related fields. Initialize old_pointm. (make_parent_window): Initialize old_pointm. (make_window): Initialize old_pointm, horizontal scroll bar type, and scroll bar height. (resize_frame_windows): Don't count top margin in new sizes. Don't use safe sizes when shrinking a frame; let the window manager do the clipping. (Fsplit_window_internal): Inherit horizontal scroll bar type and height. (Fdelete_window_internal): Unchain old_pointm marker. (window_scroll_pixel_based, Fscroll_other_window): Adjust old_pointm. (Fwindow_text_width, Fwindow_text_height): New argument "pixelwise". (struct saved_window): New fields, old_pointm, hscroll_whole, suspend_auto_hscroll, scroll_bar_height and horizontal_scroll_bar_type. (Fset_window_configuration, save_window_save): Set new fields of saved_window. (apply_window_adjustment): Don't call adjust_window_margins. (set_window_margins): Don't change margins if new sizes don't fit into window. (set_window_scroll_bars): New argument "horizontal_type". Handle horizontal scroll bars. Don't change scroll bars if they don't fit into window. (Fset_window_scroll_bars): New argument "horizontal_type". (Fwindow_scroll_bars): Return values for horizontal scroll bars. (compare_window_configurations): Compare horizontal scroll bar settings. * xdisp.c (window_text_bottom_y, window_box_height): Count in horizontal scroll bar height. (pixel_to_glyph_coords, init_xdisp): Use FRAME_TOTAL_LINES instead of FRAME_LINES. (remember_mouse_glyph): Case ON_SCROLL_BAR changed to ON_VERTICAL_SCROLL_BAR. (with_echo_area_buffer): Initialize old_pointm. (with_echo_area_buffer_unwind_data): Store old_pointm values in vector. (unwind_with_echo_area_buffer): Handle old_pointm. (update_tool_bar): Set do_update when the tool bar window has at least one line (since this is what the user sets). (MAX_FRAME_TOOL_BAR_HEIGHT): Remove macro. (redisplay_tool_bar): Return early when toolbar has zero lines. Call x_change_tool_bar_height. Don't use max_tool_bar_height. (hscroll_window_tree): Handle suspension of auto_hscroll and old_pointm. (set_horizontal_scroll_bar): New function. (redisplay_window): Set ignore_mouse_drag_p when tool bar has more than one line. Handle horizontal scroll bars. (note_mouse_highlight): Handle horizontal scrol bars. (expose_frame): Set dimensions of XRectangle from frame's text sizes. (Vvoid_text_area_pointer): Update doc-string. * xfns.c (x_set_menu_bar_lines): Use adjust_frame_size. (x_change_tool_bar_height, x_set_scroll_bar_default_height) (x_set_internal_border_width): New functions. (x_set_tool_bar_lines): Call x_change_tool_bar_height. (unwind_create_frame_1): Remove. (Fx_create_frame): Handle horizontal scroll bars. Use official field of frame structure to inhibit running window-configuration-change-hook. (x_create_tip_frame): Call SET_FRAME_LINES and change_frame_size pixelwise. Handle frame's official field. (x_frame_parm_handlers): Add x_set_scroll_bar_height, x_set_horizontal_scroll_bars, x_set_left_fringe, x_set_right_fringe. * xmenu.c (update_frame_menubar, free_frame_menubar): Use adjust_frame_size. * xterm.h (struct x_display_info): Add horizontal_scroll_bar_cursor and Xatom_Horizontal_Scrollbar slots. (struct scroll_bar): Add horizontal slot. (HORIZONTAL_SCROLL_BAR_INSIDE_HEIGHT) (HORIZONTAL_SCROLL_BAR_LEFT_RANGE) (HORIZONTAL_SCROLL_BAR_INSIDE_WIDTH): New macros. (HORIZONTAL_SCROLL_BAR_LEFT_BORDER) (HORIZONTAL_SCROLL_BAR_RIGHT_BORDER) (HORIZONTAL_SCROLL_BAR_TOP_BORDER) (HORIZONTAL_SCROLL_BAR_BOTTOM_BORDER) (HORIZONTAL_SCROLL_BAR_MIN_HANDLE): Define. (x_clear_under_internal_border): Remove. * xterm.c (XTmouse_position): Handle horizontal scroll bars. (x_window_to_scroll_bar): New argument TYPE. Update callers. (x_send_scroll_bar_event, x_scroll_bar_create): New arguments HORIZONTAL. Update callers. (horizontal_action_hook_id): New action hook id. (x_horizontal_scroll_bar_to_input_event) (x_create_horizontal_toolkit_scroll_bar) (xt_horizontal_action_hook) (x_set_toolkit_horizontal_scroll_bar_thumb) (XTset_horizontal_scroll_bar, x_net_wm_state) (x_horizontal_scroll_bar_report_motion): New functions. (xg_scroll_callback, x_scroll_bar_handle_click): Handle horizontal scroll bars. (SCROLL_BAR_HORIZONTAL_NAME): Define. (XTset_vertical_scroll_bar): Attempt to clear areas not covered by scroll bar. (XTcondemn_scroll_bars, XTredeem_scroll_bar): Rewrite. Handle horizontal scroll bars. (handle_one_xevent): Handle horizontal scroll bar events. Call x_net_wm_state. (x_set_window_size_1, x_wm_set_size_hint): Don't call check_frame_size. (x_set_window_size): Don't call check_frame_size and do_pending_window_change. (x_term_init): Init horizontal_scroll_bar_cursor display info. (x_create_terminal): Add set_horizontal_scroll_bar_hook. (x_scroll_bar_set_handle): Add some checks when calling x_clear_area.
Diffstat (limited to 'src/w32term.c')
-rw-r--r--src/w32term.c615
1 files changed, 489 insertions, 126 deletions
diff --git a/src/w32term.c b/src/w32term.c
index fd902ee7cd5..dfda29fb903 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -158,8 +158,11 @@ DWORD dwMainThreadId = 0;
158HANDLE hMainThread = NULL; 158HANDLE hMainThread = NULL;
159 159
160int vertical_scroll_bar_min_handle; 160int vertical_scroll_bar_min_handle;
161int horizontal_scroll_bar_min_handle;
161int vertical_scroll_bar_top_border; 162int vertical_scroll_bar_top_border;
162int vertical_scroll_bar_bottom_border; 163int vertical_scroll_bar_bottom_border;
164int horizontal_scroll_bar_left_border;
165int horizontal_scroll_bar_right_border;
163 166
164int last_scroll_bar_drag_pos; 167int last_scroll_bar_drag_pos;
165 168
@@ -455,7 +458,7 @@ x_set_frame_alpha (struct frame *f)
455 if (!pfnSetLayeredWindowAttributes) 458 if (!pfnSetLayeredWindowAttributes)
456 return; 459 return;
457 460
458 if (dpyinfo->x_highlight_frame == f) 461 if (dpyinfo->w32_focus_frame == f)
459 alpha = f->alpha[0]; 462 alpha = f->alpha[0];
460 else 463 else
461 alpha = f->alpha[1]; 464 alpha = f->alpha[1];
@@ -3337,11 +3340,15 @@ note_mouse_movement (struct frame *frame, MSG *msg)
3337 Mouse Face 3340 Mouse Face
3338 ************************************************************************/ 3341 ************************************************************************/
3339 3342
3340static struct scroll_bar *x_window_to_scroll_bar (Window); 3343static struct scroll_bar *x_window_to_scroll_bar (Window, int);
3341static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, 3344static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
3342 enum scroll_bar_part *, 3345 enum scroll_bar_part *,
3343 Lisp_Object *, Lisp_Object *, 3346 Lisp_Object *, Lisp_Object *,
3344 unsigned long *); 3347 unsigned long *);
3348static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
3349 enum scroll_bar_part *,
3350 Lisp_Object *, Lisp_Object *,
3351 unsigned long *);
3345static void x_check_fullscreen (struct frame *); 3352static void x_check_fullscreen (struct frame *);
3346 3353
3347static void 3354static void
@@ -3349,6 +3356,7 @@ w32_define_cursor (Window window, Cursor cursor)
3349{ 3356{
3350 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0); 3357 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3351} 3358}
3359
3352/* Return the current position of the mouse. 3360/* Return the current position of the mouse.
3353 *fp should be a frame which indicates which display to ask about. 3361 *fp should be a frame which indicates which display to ask about.
3354 3362
@@ -3380,7 +3388,14 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3380 block_input (); 3388 block_input ();
3381 3389
3382 if (dpyinfo->last_mouse_scroll_bar && insist == 0) 3390 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
3383 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); 3391 {
3392 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
3393
3394 if (bar->horizontal)
3395 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3396 else
3397 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3398 }
3384 else 3399 else
3385 { 3400 {
3386 POINT pt; 3401 POINT pt;
@@ -3408,7 +3423,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3408 if (! f1) 3423 if (! f1)
3409 { 3424 {
3410 struct scroll_bar *bar 3425 struct scroll_bar *bar
3411 = x_window_to_scroll_bar (WindowFromPoint (pt)); 3426 = x_window_to_scroll_bar (WindowFromPoint (pt), 2);
3412 3427
3413 if (bar) 3428 if (bar)
3414 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 3429 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
@@ -3475,12 +3490,12 @@ w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event)
3475 3490
3476/* Scroll bar support. */ 3491/* Scroll bar support. */
3477 3492
3478/* Given a window ID, find the struct scroll_bar which manages it. 3493/* Given a window ID, find the struct scroll_bar which manages it
3479 This can be called in GC, so we have to make sure to strip off mark 3494 vertically. This can be called in GC, so we have to make sure to
3480 bits. */ 3495 strip off mark bits. */
3481 3496
3482static struct scroll_bar * 3497static struct scroll_bar *
3483x_window_to_scroll_bar (Window window_id) 3498x_window_to_scroll_bar (Window window_id, int type)
3484{ 3499{
3485 Lisp_Object tail, frame; 3500 Lisp_Object tail, frame;
3486 3501
@@ -3498,7 +3513,10 @@ x_window_to_scroll_bar (Window window_id)
3498 condemned = Qnil, 3513 condemned = Qnil,
3499 ! NILP (bar)); 3514 ! NILP (bar));
3500 bar = XSCROLL_BAR (bar)->next) 3515 bar = XSCROLL_BAR (bar)->next)
3501 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id) 3516 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id
3517 && (type = 2
3518 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
3519 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
3502 return XSCROLL_BAR (bar); 3520 return XSCROLL_BAR (bar);
3503 } 3521 }
3504 3522
@@ -3507,7 +3525,7 @@ x_window_to_scroll_bar (Window window_id)
3507 3525
3508 3526
3509 3527
3510/* Set the thumb size and position of scroll bar BAR. We are currently 3528/* Set the thumb size and position of vertical scroll bar BAR. We are currently
3511 displaying PORTION out of a whole WHOLE, and our position POSITION. */ 3529 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3512 3530
3513static void 3531static void
@@ -3581,16 +3599,49 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
3581 unblock_input (); 3599 unblock_input ();
3582} 3600}
3583 3601
3602/* Set the thumb size and position of horizontal scroll bar BAR. We are currently
3603 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3604
3605static void
3606w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
3607 int portion, int position, int whole)
3608{
3609 Window w = SCROLL_BAR_W32_WINDOW (bar);
3610 SCROLLINFO si;
3611
3612 block_input ();
3613
3614 si.cbSize = sizeof (si);
3615 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
3616 si.nMin = 0;
3617 si.nMax = whole;
3618 /* Allow nPage to be one larger than nPos so we don't allow to scroll
3619 an already fully visible buffer. */
3620 si.nPage = min (portion, si.nMax) + 1;
3621 si.nPos = min (position, si.nMax);
3622 SetScrollInfo (w, SB_CTL, &si, TRUE);
3623
3624 unblock_input ();
3625}
3626
3584 3627
3585/************************************************************************ 3628/************************************************************************
3586 Scroll bars, general 3629 Scroll bars, general
3587 ************************************************************************/ 3630 ************************************************************************/
3588 3631
3589static HWND 3632static HWND
3590my_create_scrollbar (struct frame * f, struct scroll_bar * bar) 3633my_create_vscrollbar (struct frame * f, struct scroll_bar * bar)
3634{
3635 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3636 WM_EMACS_CREATEVSCROLLBAR, (WPARAM) f,
3637 (LPARAM) bar);
3638}
3639
3640static HWND
3641my_create_hscrollbar (struct frame * f, struct scroll_bar * bar)
3591{ 3642{
3592 return (HWND) SendMessage (FRAME_W32_WINDOW (f), 3643 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3593 WM_EMACS_CREATESCROLLBAR, (WPARAM) f, 3644 WM_EMACS_CREATEHSCROLLBAR, (WPARAM) f,
3594 (LPARAM) bar); 3645 (LPARAM) bar);
3595} 3646}
3596 3647
@@ -3660,7 +3711,7 @@ my_bring_window_to_top (HWND hwnd)
3660 scroll bar. */ 3711 scroll bar. */
3661 3712
3662static struct scroll_bar * 3713static struct scroll_bar *
3663x_scroll_bar_create (struct window *w, int top, int left, int width, int height) 3714x_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal)
3664{ 3715{
3665 struct frame *f = XFRAME (WINDOW_FRAME (w)); 3716 struct frame *f = XFRAME (WINDOW_FRAME (w));
3666 HWND hwnd; 3717 HWND hwnd;
@@ -3679,16 +3730,24 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
3679 bar->start = 0; 3730 bar->start = 0;
3680 bar->end = 0; 3731 bar->end = 0;
3681 bar->dragging = 0; 3732 bar->dragging = 0;
3733 bar->horizontal = horizontal;
3682 3734
3683 /* Requires geometry to be set before call to create the real window */ 3735 /* Requires geometry to be set before call to create the real window */
3684 3736
3685 hwnd = my_create_scrollbar (f, bar); 3737 if (horizontal)
3738 hwnd = my_create_hscrollbar (f, bar);
3739 else
3740 hwnd = my_create_vscrollbar (f, bar);
3686 3741
3687 si.cbSize = sizeof (si); 3742 si.cbSize = sizeof (si);
3688 si.fMask = SIF_ALL; 3743 si.fMask = SIF_ALL;
3689 si.nMin = 0; 3744 si.nMin = 0;
3690 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) 3745 if (horizontal)
3691 + VERTICAL_SCROLL_BAR_MIN_HANDLE; 3746 si.nMax = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width)
3747 + HORIZONTAL_SCROLL_BAR_MIN_HANDLE;
3748 else
3749 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3750 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3692 si.nPage = si.nMax; 3751 si.nPage = si.nMax;
3693 si.nPos = 0; 3752 si.nPos = 0;
3694 3753
@@ -3724,15 +3783,18 @@ x_scroll_bar_remove (struct scroll_bar *bar)
3724 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar)); 3783 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3725 3784
3726 /* Dissociate this scroll bar from its window. */ 3785 /* Dissociate this scroll bar from its window. */
3727 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); 3786 if (bar->horizontal)
3787 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
3788 else
3789 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
3728 3790
3729 unblock_input (); 3791 unblock_input ();
3730} 3792}
3731 3793
3732/* Set the handle of the vertical scroll bar for WINDOW to indicate 3794/* Set the handle of the vertical scroll bar for WINDOW to indicate that
3733 that we are displaying PORTION characters out of a total of WHOLE 3795 we are displaying PORTION characters out of a total of WHOLE
3734 characters, starting at POSITION. If WINDOW has no scroll bar, 3796 characters, starting at POSITION. If WINDOW has no vertical scroll
3735 create one. */ 3797 bar, create one. */
3736static void 3798static void
3737w32_set_vertical_scroll_bar (struct window *w, 3799w32_set_vertical_scroll_bar (struct window *w,
3738 int portion, int whole, int position) 3800 int portion, int whole, int position)
@@ -3765,7 +3827,7 @@ w32_set_vertical_scroll_bar (struct window *w,
3765 } 3827 }
3766 unblock_input (); 3828 unblock_input ();
3767 3829
3768 bar = x_scroll_bar_create (w, top, left, width, height); 3830 bar = x_scroll_bar_create (w, left, top, width, height, 0);
3769 } 3831 }
3770 else 3832 else
3771 { 3833 {
@@ -3829,6 +3891,106 @@ w32_set_vertical_scroll_bar (struct window *w,
3829 wset_vertical_scroll_bar (w, barobj); 3891 wset_vertical_scroll_bar (w, barobj);
3830} 3892}
3831 3893
3894/* Set the handle of the horizontal scroll bar for WINDOW to indicate
3895 that we are displaying PORTION characters out of a total of WHOLE
3896 characters, starting at POSITION. If WINDOW has no horizontal scroll
3897 bar, create one. */
3898static void
3899w32_set_horizontal_scroll_bar (struct window *w,
3900 int portion, int whole, int position)
3901{
3902 struct frame *f = XFRAME (w->frame);
3903 Lisp_Object barobj;
3904 struct scroll_bar *bar;
3905 int top, height, left, width;
3906 int window_x, window_width;
3907 int clear_left = WINDOW_LEFT_EDGE_X (w);
3908 int clear_width = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3909
3910 /* Get window dimensions. */
3911 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
3912 left = window_x;
3913 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
3914 width = window_width;
3915 top = WINDOW_SCROLL_BAR_AREA_Y (w);
3916
3917 /* Does the scroll bar exist yet? */
3918 if (NILP (w->horizontal_scroll_bar))
3919 {
3920 HDC hdc;
3921 block_input ();
3922 if (width > 0 && height > 0)
3923 {
3924 hdc = get_frame_dc (f);
3925 w32_clear_area (f, hdc, clear_left, top, clear_width, height);
3926 release_frame_dc (f, hdc);
3927 }
3928 unblock_input ();
3929
3930 bar = x_scroll_bar_create (w, left, top, width, height, 1);
3931 }
3932 else
3933 {
3934 /* It may just need to be moved and resized. */
3935 HWND hwnd;
3936
3937 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
3938 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3939
3940 /* If already correctly positioned, do nothing. */
3941 if (bar->left == left && bar->top == top
3942 && bar->width == width && bar->height == height)
3943 {
3944 /* Redraw after clear_frame. */
3945 if (!my_show_window (f, hwnd, SW_NORMAL))
3946 InvalidateRect (hwnd, NULL, FALSE);
3947 }
3948 else
3949 {
3950 HDC hdc;
3951 SCROLLINFO si;
3952
3953 block_input ();
3954 if (width && height)
3955 {
3956 hdc = get_frame_dc (f);
3957 /* Since Windows scroll bars are smaller than the space reserved
3958 for them on the frame, we have to clear "under" them. */
3959 w32_clear_area (f, hdc, clear_left, top, clear_width, height);
3960 release_frame_dc (f, hdc);
3961 }
3962 /* Make sure scroll bar is "visible" before moving, to ensure the
3963 area of the parent window now exposed will be refreshed. */
3964 my_show_window (f, hwnd, SW_HIDE);
3965 MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
3966
3967 /* +++ SetScrollInfo +++ */
3968 si.cbSize = sizeof (si);
3969 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
3970 si.nMin = 0;
3971 si.nMax = whole;
3972 si.nPage = min (portion, si.nMax) + 1;
3973 si.nPos = min (position, si.nMax);
3974 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3975
3976 my_show_window (f, hwnd, SW_NORMAL);
3977 /* InvalidateRect (w, NULL, FALSE); */
3978
3979 /* Remember new settings. */
3980 bar->left = left;
3981 bar->top = top;
3982 bar->width = width;
3983 bar->height = height;
3984
3985 unblock_input ();
3986 }
3987 }
3988
3989 w32_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
3990 XSETVECTOR (barobj, bar);
3991 wset_horizontal_scroll_bar (w, barobj);
3992}
3993
3832 3994
3833/* The following three hooks are used when we're doing a thorough 3995/* The following three hooks are used when we're doing a thorough
3834 redisplay of the frame. We don't explicitly know which scroll bars 3996 redisplay of the frame. We don't explicitly know which scroll bars
@@ -3845,17 +4007,22 @@ w32_set_vertical_scroll_bar (struct window *w,
3845static void 4007static void
3846w32_condemn_scroll_bars (struct frame *frame) 4008w32_condemn_scroll_bars (struct frame *frame)
3847{ 4009{
3848 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ 4010 if (!NILP (FRAME_SCROLL_BARS (frame)))
3849 while (! NILP (FRAME_SCROLL_BARS (frame)))
3850 { 4011 {
3851 Lisp_Object bar; 4012 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3852 bar = FRAME_SCROLL_BARS (frame); 4013 {
3853 fset_scroll_bars (frame, XSCROLL_BAR (bar)->next); 4014 /* Prepend scrollbars to already condemned ones. */
3854 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); 4015 Lisp_Object last = FRAME_SCROLL_BARS (frame);
3855 XSCROLL_BAR (bar)->prev = Qnil; 4016
3856 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) 4017 while (!NILP (XSCROLL_BAR (last)->next))
3857 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; 4018 last = XSCROLL_BAR (last)->next;
3858 fset_condemned_scroll_bars (frame, bar); 4019
4020 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4021 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
4022 }
4023
4024 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
4025 fset_scroll_bars (frame, Qnil);
3859 } 4026 }
3860} 4027}
3861 4028
@@ -3864,47 +4031,84 @@ w32_condemn_scroll_bars (struct frame *frame)
3864 Note that WINDOW isn't necessarily condemned at all. */ 4031 Note that WINDOW isn't necessarily condemned at all. */
3865 4032
3866static void 4033static void
3867w32_redeem_scroll_bar (struct window *window) 4034w32_redeem_scroll_bar (struct window *w)
3868{ 4035{
3869 struct scroll_bar *bar; 4036 struct scroll_bar *bar;
3870 Lisp_Object barobj; 4037 Lisp_Object barobj;
3871 struct frame *f; 4038 struct frame *f;
3872 4039
3873 /* We can't redeem this window's scroll bar if it doesn't have one. */ 4040 /* We can't redeem this window's scroll bar if it doesn't have one. */
3874 if (NILP (window->vertical_scroll_bar)) 4041 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
3875 emacs_abort (); 4042 emacs_abort ();
3876 4043
3877 bar = XSCROLL_BAR (window->vertical_scroll_bar); 4044 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
3878
3879 /* Unlink it from the condemned list. */
3880 f = XFRAME (WINDOW_FRAME (window));
3881 if (NILP (bar->prev))
3882 { 4045 {
3883 /* If the prev pointer is nil, it must be the first in one of 4046 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3884 the lists. */ 4047 /* Unlink it from the condemned list. */
3885 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar)) 4048 f = XFRAME (WINDOW_FRAME (w));
3886 /* It's not condemned. Everything's fine. */ 4049 if (NILP (bar->prev))
3887 return; 4050 {
3888 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), 4051 /* If the prev pointer is nil, it must be the first in one of
3889 window->vertical_scroll_bar)) 4052 the lists. */
3890 fset_condemned_scroll_bars (f, bar->next); 4053 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
4054 /* It's not condemned. Everything's fine. */
4055 goto horizontal;
4056 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4057 w->vertical_scroll_bar))
4058 fset_condemned_scroll_bars (f, bar->next);
4059 else
4060 /* If its prev pointer is nil, it must be at the front of
4061 one or the other! */
4062 emacs_abort ();
4063 }
3891 else 4064 else
3892 /* If its prev pointer is nil, it must be at the front of 4065 XSCROLL_BAR (bar->prev)->next = bar->next;
3893 one or the other! */ 4066
3894 emacs_abort (); 4067 if (! NILP (bar->next))
4068 XSCROLL_BAR (bar->next)->prev = bar->prev;
4069
4070 bar->next = FRAME_SCROLL_BARS (f);
4071 bar->prev = Qnil;
4072 XSETVECTOR (barobj, bar);
4073 fset_scroll_bars (f, barobj);
4074 if (! NILP (bar->next))
4075 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3895 } 4076 }
3896 else
3897 XSCROLL_BAR (bar->prev)->next = bar->next;
3898 4077
3899 if (! NILP (bar->next)) 4078 horizontal:
3900 XSCROLL_BAR (bar->next)->prev = bar->prev; 4079 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
4080 {
4081 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
4082 /* Unlink it from the condemned list. */
4083 f = XFRAME (WINDOW_FRAME (w));
4084 if (NILP (bar->prev))
4085 {
4086 /* If the prev pointer is nil, it must be the first in one of
4087 the lists. */
4088 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
4089 /* It's not condemned. Everything's fine. */
4090 return;
4091 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4092 w->horizontal_scroll_bar))
4093 fset_condemned_scroll_bars (f, bar->next);
4094 else
4095 /* If its prev pointer is nil, it must be at the front of
4096 one or the other! */
4097 emacs_abort ();
4098 }
4099 else
4100 XSCROLL_BAR (bar->prev)->next = bar->next;
3901 4101
3902 bar->next = FRAME_SCROLL_BARS (f); 4102 if (! NILP (bar->next))
3903 bar->prev = Qnil; 4103 XSCROLL_BAR (bar->next)->prev = bar->prev;
3904 XSETVECTOR (barobj, bar); 4104
3905 fset_scroll_bars (f, barobj); 4105 bar->next = FRAME_SCROLL_BARS (f);
3906 if (! NILP (bar->next)) 4106 bar->prev = Qnil;
3907 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); 4107 XSETVECTOR (barobj, bar);
4108 fset_scroll_bars (f, barobj);
4109 if (! NILP (bar->next))
4110 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4111 }
3908} 4112}
3909 4113
3910/* Remove all scroll bars on FRAME that haven't been saved since the 4114/* Remove all scroll bars on FRAME that haven't been saved since the
@@ -3935,8 +4139,9 @@ w32_judge_scroll_bars (struct frame *f)
3935 and they should get garbage-collected. */ 4139 and they should get garbage-collected. */
3936} 4140}
3937 4141
3938/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind 4142/* Handle a mouse click on the vertical scroll bar BAR. If
3939 is set to something other than NO_EVENT, it is enqueued. 4143 *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
4144 enqueued.
3940 4145
3941 This may be called from a signal handler, so we have to ignore GC 4146 This may be called from a signal handler, so we have to ignore GC
3942 mark bits. */ 4147 mark bits. */
@@ -4043,9 +4248,120 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4043 } 4248 }
4044} 4249}
4045 4250
4046/* Return information to the user about the current position of the mouse 4251/* Handle a mouse click on the horizontal scroll bar BAR. If
4047 on the scroll bar. */ 4252 *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
4253 enqueued.
4254
4255 This may be called from a signal handler, so we have to ignore GC
4256 mark bits. */
4048 4257
4258static int
4259w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4260 struct input_event *emacs_event)
4261{
4262 if (! WINDOWP (bar->window))
4263 emacs_abort ();
4264
4265 emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
4266 emacs_event->code = 0;
4267 /* not really meaningful to distinguish left/right */
4268 emacs_event->modifiers = msg->dwModifiers;
4269 emacs_event->frame_or_window = bar->window;
4270 emacs_event->arg = Qnil;
4271 emacs_event->timestamp = msg->msg.time;
4272
4273 {
4274 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
4275 int x;
4276 int dragging = bar->dragging;
4277 SCROLLINFO si;
4278
4279 si.cbSize = sizeof (si);
4280 si.fMask = SIF_POS;
4281
4282 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4283 x = si.nPos;
4284
4285 bar->dragging = 0;
4286 FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
4287
4288 switch (LOWORD (msg->msg.wParam))
4289 {
4290 case SB_LINELEFT:
4291 emacs_event->part = scroll_bar_left_arrow;
4292 break;
4293 case SB_LINERIGHT:
4294 emacs_event->part = scroll_bar_right_arrow;
4295 break;
4296 case SB_PAGELEFT:
4297 emacs_event->part = scroll_bar_before_handle;
4298 break;
4299 case SB_PAGERIGHT:
4300 emacs_event->part = scroll_bar_after_handle;
4301 break;
4302 case SB_LEFT:
4303 emacs_event->part = scroll_bar_horizontal_handle;
4304 x = 0;
4305 break;
4306 case SB_RIGHT:
4307 emacs_event->part = scroll_bar_horizontal_handle;
4308 x = left_range;
4309 break;
4310 case SB_THUMBTRACK:
4311 case SB_THUMBPOSITION:
4312 if (HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width) <= 0xffff)
4313 x = HIWORD (msg->msg.wParam);
4314 bar->dragging = 1;
4315 emacs_event->part = scroll_bar_horizontal_handle;
4316
4317 /* "Silently" update current position. */
4318 {
4319 SCROLLINFO si;
4320
4321 si.cbSize = sizeof (si);
4322 si.fMask = SIF_POS;
4323 si.nPos = min (x, XWINDOW (bar->window)->hscroll_whole - 1);
4324 /* Remember apparent position (we actually lag behind the real
4325 position, so don't set that directly). */
4326 last_scroll_bar_drag_pos = x;
4327
4328 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4329 }
4330 break;
4331 case SB_ENDSCROLL:
4332 /* If this is the end of a drag sequence, then reset the scroll
4333 handle size to normal and do a final redraw. Otherwise do
4334 nothing. */
4335 if (dragging)
4336 {
4337 SCROLLINFO si;
4338 int start = bar->start;
4339 int end = bar->end;
4340
4341 si.cbSize = sizeof (si);
4342/** si.fMask = SIF_PAGE | SIF_POS; **/
4343 si.fMask = SIF_POS;
4344/** si.nPage = end - start + HORIZONTAL_SCROLL_BAR_MIN_HANDLE; **/
4345 si.nPos = min (last_scroll_bar_drag_pos,
4346 XWINDOW (bar->window)->hscroll_whole - 1);
4347/** si.nPos = last_scroll_bar_drag_pos; **/
4348 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
4349 }
4350 /* fall through */
4351 default:
4352 emacs_event->kind = NO_EVENT;
4353 return FALSE;
4354 }
4355
4356 XSETINT (emacs_event->x, x);
4357 XSETINT (emacs_event->y, left_range);
4358
4359 return TRUE;
4360 }
4361}
4362
4363/* Return information to the user about the current position of the mouse
4364 on the vertical scroll bar. */
4049static void 4365static void
4050x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window, 4366x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
4051 enum scroll_bar_part *part, 4367 enum scroll_bar_part *part,
@@ -4100,6 +4416,62 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
4100 unblock_input (); 4416 unblock_input ();
4101} 4417}
4102 4418
4419/* Return information to the user about the current position of the mouse
4420 on the horizontal scroll bar. */
4421static void
4422x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
4423 enum scroll_bar_part *part,
4424 Lisp_Object *x, Lisp_Object *y,
4425 unsigned long *time)
4426{
4427 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
4428 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
4429 Window w = SCROLL_BAR_W32_WINDOW (bar);
4430 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4431 int pos;
4432 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
4433 SCROLLINFO si;
4434
4435 block_input ();
4436
4437 *fp = f;
4438 *bar_window = bar->window;
4439
4440 si.cbSize = sizeof (si);
4441 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4442
4443 GetScrollInfo (w, SB_CTL, &si);
4444 pos = si.nPos;
4445 left_range = si.nMax - si.nPage + 1;
4446
4447 switch (LOWORD (dpyinfo->last_mouse_scroll_bar_pos))
4448 {
4449 case SB_THUMBPOSITION:
4450 case SB_THUMBTRACK:
4451 *part = scroll_bar_handle;
4452 if (HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width) <= 0xffff)
4453 pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos);
4454 break;
4455 case SB_LINERIGHT:
4456 *part = scroll_bar_handle;
4457 pos++;
4458 break;
4459 default:
4460 *part = scroll_bar_handle;
4461 break;
4462 }
4463
4464 XSETINT (*y, pos);
4465 XSETINT (*x, left_range);
4466
4467 f->mouse_moved = 0;
4468 dpyinfo->last_mouse_scroll_bar = NULL;
4469
4470 *time = dpyinfo->last_mouse_movement_time;
4471
4472 unblock_input ();
4473}
4474
4103 4475
4104/* The screen has been cleared so we may have changed foreground or 4476/* The screen has been cleared so we may have changed foreground or
4105 background colors, and the scroll bars may need to be redrawn. 4477 background colors, and the scroll bars may need to be redrawn.
@@ -4114,7 +4486,8 @@ x_scroll_bar_clear (struct frame *f)
4114 /* We can have scroll bars even if this is 0, 4486 /* We can have scroll bars even if this is 0,
4115 if we just turned off scroll bar mode. 4487 if we just turned off scroll bar mode.
4116 But in that case we should not clear them. */ 4488 But in that case we should not clear them. */
4117 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) 4489 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4490 || FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4118 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); 4491 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4119 bar = XSCROLL_BAR (bar)->next) 4492 bar = XSCROLL_BAR (bar)->next)
4120 { 4493 {
@@ -4589,10 +4962,20 @@ w32_read_socket (struct terminal *terminal,
4589 construct_drag_n_drop (&inev, &msg, f); 4962 construct_drag_n_drop (&inev, &msg, f);
4590 break; 4963 break;
4591 4964
4965 case WM_HSCROLL:
4966 {
4967 struct scroll_bar *bar =
4968 x_window_to_scroll_bar ((HWND)msg.msg.lParam, 1);
4969
4970 if (bar)
4971 w32_horizontal_scroll_bar_handle_click (bar, &msg, &inev);
4972 break;
4973 }
4974
4592 case WM_VSCROLL: 4975 case WM_VSCROLL:
4593 { 4976 {
4594 struct scroll_bar *bar = 4977 struct scroll_bar *bar =
4595 x_window_to_scroll_bar ((HWND)msg.msg.lParam); 4978 x_window_to_scroll_bar ((HWND)msg.msg.lParam, 0);
4596 4979
4597 if (bar) 4980 if (bar)
4598 w32_scroll_bar_handle_click (bar, &msg, &inev); 4981 w32_scroll_bar_handle_click (bar, &msg, &inev);
@@ -4787,10 +5170,6 @@ w32_read_socket (struct terminal *terminal,
4787 change_frame_size (f, text_width, text_height, 0, 1, 0, 1); 5170 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
4788 SET_FRAME_GARBAGED (f); 5171 SET_FRAME_GARBAGED (f);
4789 cancel_mouse_face (f); 5172 cancel_mouse_face (f);
4790 /* Do we want to set these here ???? */
4791/** FRAME_PIXEL_WIDTH (f) = width; **/
4792/** FRAME_TEXT_WIDTH (f) = text_width; **/
4793/** FRAME_PIXEL_HEIGHT (f) = height; **/
4794 f->win_gravity = NorthWestGravity; 5173 f->win_gravity = NorthWestGravity;
4795 } 5174 }
4796 } 5175 }
@@ -5430,8 +5809,6 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
5430 FRAME_COLUMN_WIDTH (f) = unit = font->average_width; 5809 FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
5431 FRAME_LINE_HEIGHT (f) = font->height; 5810 FRAME_LINE_HEIGHT (f) = font->height;
5432 5811
5433 compute_fringe_widths (f, 1);
5434
5435 /* Compute number of scrollbar columns. */ 5812 /* Compute number of scrollbar columns. */
5436 unit = FRAME_COLUMN_WIDTH (f); 5813 unit = FRAME_COLUMN_WIDTH (f);
5437 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) 5814 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
@@ -5451,8 +5828,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
5451 doing it because it's done in Fx_show_tip, and it leads to 5828 doing it because it's done in Fx_show_tip, and it leads to
5452 problems because the tip frame has no widget. */ 5829 problems because the tip frame has no widget. */
5453 if (NILP (tip_frame) || XFRAME (tip_frame) != f) 5830 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5454 x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 5831 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
5455 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1); 5832 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0);
5456 } 5833 }
5457 5834
5458 /* X version sets font of input methods here also. */ 5835 /* X version sets font of input methods here also. */
@@ -5649,6 +6026,7 @@ w32fullscreen_hook (struct frame *f)
5649 HWND hwnd = FRAME_W32_WINDOW(f); 6026 HWND hwnd = FRAME_W32_WINDOW(f);
5650 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE); 6027 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
5651 RECT rect; 6028 RECT rect;
6029 enum fullscreen_type prev_fsmode = FRAME_PREV_FSMODE (f);
5652 6030
5653 block_input(); 6031 block_input();
5654 f->want_fullscreen &= ~FULLSCREEN_WAIT; 6032 f->want_fullscreen &= ~FULLSCREEN_WAIT;
@@ -5670,7 +6048,14 @@ w32fullscreen_hook (struct frame *f)
5670 if (f->want_fullscreen == FULLSCREEN_NONE) 6048 if (f->want_fullscreen == FULLSCREEN_NONE)
5671 ShowWindow (hwnd, SW_SHOWNORMAL); 6049 ShowWindow (hwnd, SW_SHOWNORMAL);
5672 else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED) 6050 else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
5673 ShowWindow (hwnd, SW_MAXIMIZE); 6051 {
6052 if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH
6053 || prev_fsmode == FULLSCREEN_HEIGHT)
6054 /* Make window normal since otherwise the subsequent
6055 maximization might fail in some cases. */
6056 ShowWindow (hwnd, SW_SHOWNORMAL);
6057 ShowWindow (hwnd, SW_MAXIMIZE);
6058 }
5674 else if (f->want_fullscreen == FULLSCREEN_BOTH) 6059 else if (f->want_fullscreen == FULLSCREEN_BOTH)
5675 { 6060 {
5676 w32_fullscreen_rect (hwnd, f->want_fullscreen, 6061 w32_fullscreen_rect (hwnd, f->want_fullscreen,
@@ -5705,70 +6090,40 @@ void
5705x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise) 6090x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
5706{ 6091{
5707 int pixelwidth, pixelheight; 6092 int pixelwidth, pixelheight;
6093 RECT rect;
5708 6094
5709 block_input (); 6095 block_input ();
5710 6096
5711 check_frame_size (f, &width, &height, pixelwise); 6097 if (pixelwise)
5712
5713 compute_fringe_widths (f, 0);
5714
5715 if (frame_resize_pixelwise)
5716 { 6098 {
5717 if (pixelwise) 6099 pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
5718 { 6100 pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
5719 pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
5720 pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
5721 }
5722 else
5723 {
5724 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
5725 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
5726 }
5727 } 6101 }
5728 else 6102 else
5729 { 6103 {
5730 /* If we don't resize frames pixelwise, round sizes to multiples 6104 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
5731 of character sizes here. Otherwise, when enforcing size hints 6105 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
5732 while processing WM_WINDOWPOSCHANGING in w32_wnd_proc, we might
5733 clip our frame rectangle to a multiple of the frame's character
5734 size and subsequently lose our mode line or scroll bar.
5735 Bug#16923 could be one possible consequence of this. Carefully
5736 reverse-engineer what WM_WINDOWPOSCHANGING does here since
5737 otherwise we might make our frame too small, see Bug#17077. */
5738 int unit_width = FRAME_COLUMN_WIDTH (f);
5739 int unit_height = FRAME_LINE_HEIGHT (f);
5740
5741 pixelwidth = (((((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f)))
5742 + FRAME_TOTAL_FRINGE_WIDTH (f))
5743 / unit_width) * unit_width)
5744 + FRAME_SCROLL_BAR_AREA_WIDTH (f)
5745 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5746
5747 pixelheight = ((((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f)))
5748 / unit_height) * unit_height)
5749 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5750 } 6106 }
5751 6107
5752 f->win_gravity = NorthWestGravity; 6108 f->win_gravity = NorthWestGravity;
5753 x_wm_set_size_hint (f, (long) 0, 0); 6109 x_wm_set_size_hint (f, (long) 0, 0);
5754 6110
5755 { 6111 f->want_fullscreen = FULLSCREEN_NONE;
5756 RECT rect; 6112 w32fullscreen_hook (f);
5757 6113
5758 rect.left = rect.top = 0; 6114 rect.left = rect.top = 0;
5759 rect.right = pixelwidth; 6115 rect.right = pixelwidth;
5760 rect.bottom = pixelheight; 6116 rect.bottom = pixelheight;
5761 6117
5762 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, 6118 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5763 FRAME_EXTERNAL_MENU_BAR (f)); 6119 FRAME_EXTERNAL_MENU_BAR (f));
5764 6120
5765 my_set_window_pos (FRAME_W32_WINDOW (f), 6121 my_set_window_pos (FRAME_W32_WINDOW (f),
5766 NULL, 6122 NULL,
5767 0, 0, 6123 0, 0,
5768 rect.right - rect.left, 6124 rect.right - rect.left,
5769 rect.bottom - rect.top, 6125 rect.bottom - rect.top,
5770 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 6126 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5771 }
5772 6127
5773 /* If w32_enable_frame_resize_hack is non-nil, immediately apply the 6128 /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
5774 new pixel sizes to the frame and its subwindows. 6129 new pixel sizes to the frame and its subwindows.
@@ -5817,6 +6172,8 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
5817 } 6172 }
5818 6173
5819 unblock_input (); 6174 unblock_input ();
6175
6176 do_pending_window_change (0);
5820} 6177}
5821 6178
5822/* Mouse warping. */ 6179/* Mouse warping. */
@@ -6156,7 +6513,8 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
6156 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); 6513 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
6157 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); 6514 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
6158 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); 6515 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
6159 SetWindowLong (window, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); 6516 SetWindowLong (window, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
6517 SetWindowLong (window, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
6160 6518
6161 leave_crit (); 6519 leave_crit ();
6162} 6520}
@@ -6243,6 +6601,7 @@ w32_initialize_display_info (Lisp_Object display_name)
6243 dpyinfo->smallest_font_height = 1; 6601 dpyinfo->smallest_font_height = 1;
6244 dpyinfo->smallest_char_width = 1; 6602 dpyinfo->smallest_char_width = 1;
6245 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW); 6603 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6604 dpyinfo->horizontal_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6246 /* TODO: dpyinfo->gray */ 6605 /* TODO: dpyinfo->gray */
6247 6606
6248 reset_mouse_highlight (&dpyinfo->mouse_highlight); 6607 reset_mouse_highlight (&dpyinfo->mouse_highlight);
@@ -6363,6 +6722,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
6363 terminal->menu_show_hook = w32_menu_show; 6722 terminal->menu_show_hook = w32_menu_show;
6364 terminal->popup_dialog_hook = w32_popup_dialog; 6723 terminal->popup_dialog_hook = w32_popup_dialog;
6365 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar; 6724 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6725 terminal->set_horizontal_scroll_bar_hook = w32_set_horizontal_scroll_bar;
6366 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars; 6726 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6367 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar; 6727 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6368 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars; 6728 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
@@ -6595,13 +6955,16 @@ w32_initialize (void)
6595 6955
6596#undef LOAD_PROC 6956#undef LOAD_PROC
6597 6957
6598 /* Ensure scrollbar handle is at least 5 pixels. */ 6958 /* Ensure scrollbar handles are at least 5 pixels. */
6599 vertical_scroll_bar_min_handle = 5; 6959 vertical_scroll_bar_min_handle = 5;
6960 horizontal_scroll_bar_min_handle = 5;
6600 6961
6601 /* For either kind of scroll bar, take account of the arrows; these 6962 /* For either kind of scroll bar, take account of the arrows; these
6602 effectively form the border of the main scroll bar range. */ 6963 effectively form the border of the main scroll bar range. */
6603 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border 6964 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6604 = GetSystemMetrics (SM_CYVSCROLL); 6965 = GetSystemMetrics (SM_CYVSCROLL);
6966 horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
6967 = GetSystemMetrics (SM_CYHSCROLL);
6605 } 6968 }
6606} 6969}
6607 6970