aboutsummaryrefslogtreecommitdiffstats
path: root/src/xterm.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/xterm.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/xterm.c')
-rw-r--r--src/xterm.c1068
1 files changed, 919 insertions, 149 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 85835a2c7c5..b4eba7fcf82 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -246,11 +246,15 @@ static void x_clip_to_row (struct window *, struct glyph_row *,
246static void x_flush (struct frame *f); 246static void x_flush (struct frame *f);
247static void x_update_begin (struct frame *); 247static void x_update_begin (struct frame *);
248static void x_update_window_begin (struct window *); 248static void x_update_window_begin (struct window *);
249static struct scroll_bar *x_window_to_scroll_bar (Display *, Window); 249static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
250static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, 250static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
251 enum scroll_bar_part *, 251 enum scroll_bar_part *,
252 Lisp_Object *, Lisp_Object *, 252 Lisp_Object *, Lisp_Object *,
253 Time *); 253 Time *);
254static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
255 enum scroll_bar_part *,
256 Lisp_Object *, Lisp_Object *,
257 Time *);
254static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *); 258static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
255static void x_check_fullscreen (struct frame *); 259static void x_check_fullscreen (struct frame *);
256static void x_check_expected_move (struct frame *, int, int); 260static void x_check_expected_move (struct frame *, int, int);
@@ -268,6 +272,7 @@ static void x_wm_set_window_state (struct frame *, int);
268static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t); 272static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
269static void x_initialize (void); 273static void x_initialize (void);
270 274
275static int get_current_wm_state (struct frame *, Window, int *, int *);
271 276
272/* Flush display of frame F. */ 277/* Flush display of frame F. */
273 278
@@ -634,10 +639,8 @@ XTframe_up_to_date (struct frame *f)
634} 639}
635 640
636 641
637/* Clear under internal border if any for non-toolkit builds. */ 642/* Clear under internal border if any (GTK has its own version). */
638 643#ifndef USE_GTK
639
640#if !defined USE_X_TOOLKIT && !defined USE_GTK
641void 644void
642x_clear_under_internal_border (struct frame *f) 645x_clear_under_internal_border (struct frame *f)
643{ 646{
@@ -3974,7 +3977,14 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3974 block_input (); 3977 block_input ();
3975 3978
3976 if (dpyinfo->last_mouse_scroll_bar && insist == 0) 3979 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
3977 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp); 3980 {
3981 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
3982
3983 if (bar->horizontal)
3984 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3985 else
3986 x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
3987 }
3978 else 3988 else
3979 { 3989 {
3980 Window root; 3990 Window root;
@@ -4118,7 +4128,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4118 { 4128 {
4119 struct scroll_bar *bar; 4129 struct scroll_bar *bar;
4120 4130
4121 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win); 4131 bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
4122 4132
4123 if (bar) 4133 if (bar)
4124 { 4134 {
@@ -4173,7 +4183,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4173 bits. */ 4183 bits. */
4174 4184
4175static struct scroll_bar * 4185static struct scroll_bar *
4176x_window_to_scroll_bar (Display *display, Window window_id) 4186x_window_to_scroll_bar (Display *display, Window window_id, int type)
4177{ 4187{
4178 Lisp_Object tail, frame; 4188 Lisp_Object tail, frame;
4179 4189
@@ -4198,8 +4208,11 @@ x_window_to_scroll_bar (Display *display, Window window_id)
4198 condemned = Qnil, 4208 condemned = Qnil,
4199 ! NILP (bar)); 4209 ! NILP (bar));
4200 bar = XSCROLL_BAR (bar)->next) 4210 bar = XSCROLL_BAR (bar)->next)
4201 if (XSCROLL_BAR (bar)->x_window == window_id && 4211 if (XSCROLL_BAR (bar)->x_window == window_id
4202 FRAME_X_DISPLAY (XFRAME (frame)) == display) 4212 && FRAME_X_DISPLAY (XFRAME (frame)) == display
4213 && (type = 2
4214 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
4215 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
4203 return XSCROLL_BAR (bar); 4216 return XSCROLL_BAR (bar);
4204 } 4217 }
4205 4218
@@ -4237,7 +4250,7 @@ x_window_to_menu_bar (Window window)
4237 4250
4238#ifdef USE_TOOLKIT_SCROLL_BARS 4251#ifdef USE_TOOLKIT_SCROLL_BARS
4239 4252
4240static void x_send_scroll_bar_event (Lisp_Object, int, int, int); 4253static void x_send_scroll_bar_event (Lisp_Object, int, int, int, bool);
4241 4254
4242/* Lisp window being scrolled. Set when starting to interact with 4255/* Lisp window being scrolled. Set when starting to interact with
4243 a toolkit scroll bar, reset to nil when ending the interaction. */ 4256 a toolkit scroll bar, reset to nil when ending the interaction. */
@@ -4251,6 +4264,7 @@ static Lisp_Object window_being_scrolled;
4251/* Id of action hook installed for scroll bars. */ 4264/* Id of action hook installed for scroll bars. */
4252 4265
4253static XtActionHookId action_hook_id; 4266static XtActionHookId action_hook_id;
4267static XtActionHookId horizontal_action_hook_id;
4254 4268
4255static Boolean xaw3d_arrow_scroll; 4269static Boolean xaw3d_arrow_scroll;
4256 4270
@@ -4288,7 +4302,7 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4288 struct scroll_bar *bar; 4302 struct scroll_bar *bar;
4289 4303
4290 x_send_scroll_bar_event (window_being_scrolled, 4304 x_send_scroll_bar_event (window_being_scrolled,
4291 scroll_bar_end_scroll, 0, 0); 4305 scroll_bar_end_scroll, 0, 0, 0);
4292 w = XWINDOW (window_being_scrolled); 4306 w = XWINDOW (window_being_scrolled);
4293 bar = XSCROLL_BAR (w->vertical_scroll_bar); 4307 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4294 4308
@@ -4306,6 +4320,49 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4306 toolkit_scroll_bar_interaction = 0; 4320 toolkit_scroll_bar_interaction = 0;
4307 } 4321 }
4308} 4322}
4323
4324
4325static void
4326xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_name,
4327 XEvent *event, String *params, Cardinal *num_params)
4328{
4329 int scroll_bar_p;
4330 const char *end_action;
4331
4332#ifdef USE_MOTIF
4333 scroll_bar_p = XmIsScrollBar (widget);
4334 end_action = "Release";
4335#else /* !USE_MOTIF i.e. use Xaw */
4336 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
4337 end_action = "EndScroll";
4338#endif /* USE_MOTIF */
4339
4340 if (scroll_bar_p
4341 && strcmp (action_name, end_action) == 0
4342 && WINDOWP (window_being_scrolled))
4343 {
4344 struct window *w;
4345 struct scroll_bar *bar;
4346
4347 x_send_scroll_bar_event (window_being_scrolled,
4348 scroll_bar_end_scroll, 0, 0, 1);
4349 w = XWINDOW (window_being_scrolled);
4350 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
4351
4352 if (bar->dragging != -1)
4353 {
4354 bar->dragging = -1;
4355 /* The thumb size is incorrect while dragging: fix it. */
4356 set_horizontal_scroll_bar (w);
4357 }
4358 window_being_scrolled = Qnil;
4359#if defined (USE_LUCID)
4360 bar->last_seen_part = scroll_bar_nowhere;
4361#endif
4362 /* Xt timeouts no longer needed. */
4363 toolkit_scroll_bar_interaction = 0;
4364 }
4365}
4309#endif /* not USE_GTK */ 4366#endif /* not USE_GTK */
4310 4367
4311/* Send a client message with message type Xatom_Scrollbar for a 4368/* Send a client message with message type Xatom_Scrollbar for a
@@ -4314,7 +4371,7 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name,
4314 amount to scroll of a whole of WHOLE. */ 4371 amount to scroll of a whole of WHOLE. */
4315 4372
4316static void 4373static void
4317x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole) 4374x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole, bool horizontal)
4318{ 4375{
4319 XEvent event; 4376 XEvent event;
4320 XClientMessageEvent *ev = &event.xclient; 4377 XClientMessageEvent *ev = &event.xclient;
@@ -4329,7 +4386,9 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
4329 4386
4330 /* Construct a ClientMessage event to send to the frame. */ 4387 /* Construct a ClientMessage event to send to the frame. */
4331 ev->type = ClientMessage; 4388 ev->type = ClientMessage;
4332 ev->message_type = FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar; 4389 ev->message_type = (horizontal
4390 ? FRAME_DISPLAY_INFO (f)->Xatom_Horizontal_Scrollbar
4391 : FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar);
4333 ev->display = FRAME_X_DISPLAY (f); 4392 ev->display = FRAME_X_DISPLAY (f);
4334 ev->window = FRAME_X_WINDOW (f); 4393 ev->window = FRAME_X_WINDOW (f);
4335 ev->format = 32; 4394 ev->format = 32;
@@ -4394,6 +4453,41 @@ x_scroll_bar_to_input_event (const XEvent *event,
4394 ievent->modifiers = 0; 4453 ievent->modifiers = 0;
4395} 4454}
4396 4455
4456/* Transform a horizontal scroll bar ClientMessage EVENT to an Emacs
4457 input event in *IEVENT. */
4458
4459static void
4460x_horizontal_scroll_bar_to_input_event (const XEvent *event,
4461 struct input_event *ievent)
4462{
4463 const XClientMessageEvent *ev = &event->xclient;
4464 Lisp_Object window;
4465 struct window *w;
4466
4467 /* See the comment in the function above. */
4468 intptr_t iw0 = ev->data.l[0];
4469 intptr_t iw1 = ev->data.l[1];
4470 intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
4471 w = (struct window *) iw;
4472
4473 XSETWINDOW (window, w);
4474
4475 ievent->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
4476 ievent->frame_or_window = window;
4477 ievent->arg = Qnil;
4478#ifdef USE_GTK
4479 ievent->timestamp = CurrentTime;
4480#else
4481 ievent->timestamp =
4482 XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
4483#endif
4484 ievent->code = 0;
4485 ievent->part = ev->data.l[2];
4486 ievent->x = make_number (ev->data.l[3]);
4487 ievent->y = make_number (ev->data.l[4]);
4488 ievent->modifiers = 0;
4489}
4490
4397 4491
4398#ifdef USE_MOTIF 4492#ifdef USE_MOTIF
4399 4493
@@ -4401,7 +4495,6 @@ x_scroll_bar_to_input_event (const XEvent *event,
4401 4495
4402#define XM_SB_MAX 10000000 4496#define XM_SB_MAX 10000000
4403 4497
4404
4405/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll 4498/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
4406 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure. 4499 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
4407 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */ 4500 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
@@ -4412,51 +4505,65 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4412 struct scroll_bar *bar = client_data; 4505 struct scroll_bar *bar = client_data;
4413 XmScrollBarCallbackStruct *cs = call_data; 4506 XmScrollBarCallbackStruct *cs = call_data;
4414 int part = -1, whole = 0, portion = 0; 4507 int part = -1, whole = 0, portion = 0;
4508 int horizontal = bar->horizontal;
4415 4509
4416 switch (cs->reason) 4510 switch (cs->reason)
4417 { 4511 {
4418 case XmCR_DECREMENT: 4512 case XmCR_DECREMENT:
4419 bar->dragging = -1; 4513 bar->dragging = -1;
4420 part = scroll_bar_up_arrow; 4514 part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow;
4421 break; 4515 break;
4422 4516
4423 case XmCR_INCREMENT: 4517 case XmCR_INCREMENT:
4424 bar->dragging = -1; 4518 bar->dragging = -1;
4425 part = scroll_bar_down_arrow; 4519 part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow;
4426 break; 4520 break;
4427 4521
4428 case XmCR_PAGE_DECREMENT: 4522 case XmCR_PAGE_DECREMENT:
4429 bar->dragging = -1; 4523 bar->dragging = -1;
4430 part = scroll_bar_above_handle; 4524 part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle;
4431 break; 4525 break;
4432 4526
4433 case XmCR_PAGE_INCREMENT: 4527 case XmCR_PAGE_INCREMENT:
4434 bar->dragging = -1; 4528 bar->dragging = -1;
4435 part = scroll_bar_below_handle; 4529 part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle;
4436 break; 4530 break;
4437 4531
4438 case XmCR_TO_TOP: 4532 case XmCR_TO_TOP:
4439 bar->dragging = -1; 4533 bar->dragging = -1;
4440 part = scroll_bar_to_top; 4534 part = horizontal ? scroll_bar_to_leftmost : scroll_bar_to_top;
4441 break; 4535 break;
4442 4536
4443 case XmCR_TO_BOTTOM: 4537 case XmCR_TO_BOTTOM:
4444 bar->dragging = -1; 4538 bar->dragging = -1;
4445 part = scroll_bar_to_bottom; 4539 part = horizontal ? scroll_bar_to_rightmost : scroll_bar_to_bottom;
4446 break; 4540 break;
4447 4541
4448 case XmCR_DRAG: 4542 case XmCR_DRAG:
4449 { 4543 {
4450 int slider_size; 4544 int slider_size;
4451 4545
4452 /* Get the slider size. */
4453 block_input (); 4546 block_input ();
4454 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL); 4547 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4455 unblock_input (); 4548 unblock_input ();
4456 4549
4457 whole = XM_SB_MAX - slider_size; 4550 if (horizontal)
4458 portion = min (cs->value, whole); 4551 {
4459 part = scroll_bar_handle; 4552 whole = bar->whole;
4553 portion = (((float) cs->value
4554 / (XM_SB_MAX - slider_size))
4555 * (whole
4556 - ((float) slider_size / XM_SB_MAX) * whole));
4557 portion = max (0, portion);
4558 part = scroll_bar_horizontal_handle;
4559 }
4560 else
4561 {
4562 whole = XM_SB_MAX - slider_size;
4563 portion = min (cs->value, whole);
4564 part = scroll_bar_handle;
4565 }
4566
4460 bar->dragging = cs->value; 4567 bar->dragging = cs->value;
4461 } 4568 }
4462 break; 4569 break;
@@ -4468,7 +4575,7 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4468 if (part >= 0) 4575 if (part >= 0)
4469 { 4576 {
4470 window_being_scrolled = bar->window; 4577 window_being_scrolled = bar->window;
4471 x_send_scroll_bar_event (bar->window, part, portion, whole); 4578 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
4472 } 4579 }
4473} 4580}
4474 4581
@@ -4497,27 +4604,42 @@ xg_scroll_callback (GtkRange *range,
4497 if (FRAME_DISPLAY_INFO (f)->grabbed != 0 4604 if (FRAME_DISPLAY_INFO (f)->grabbed != 0
4498 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4)) 4605 && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
4499 { 4606 {
4500 part = scroll_bar_handle; 4607 if (bar->horizontal)
4501 whole = gtk_adjustment_get_upper (adj) - 4608 {
4502 gtk_adjustment_get_page_size (adj); 4609 part = scroll_bar_horizontal_handle;
4503 portion = min ((int)value, whole); 4610 whole = (int)(gtk_adjustment_get_upper (adj) -
4504 bar->dragging = portion; 4611 gtk_adjustment_get_page_size (adj));
4505 } 4612 portion = min ((int)value, whole);
4613 bar->dragging = portion;
4614 }
4615 else
4616 {
4617 part = scroll_bar_handle;
4618 whole = gtk_adjustment_get_upper (adj) -
4619 gtk_adjustment_get_page_size (adj);
4620 portion = min ((int)value, whole);
4621 bar->dragging = portion;
4622 }
4623 }
4506 break; 4624 break;
4507 case GTK_SCROLL_STEP_BACKWARD: 4625 case GTK_SCROLL_STEP_BACKWARD:
4508 part = scroll_bar_up_arrow; 4626 part = (bar->horizontal
4627 ? scroll_bar_left_arrow : scroll_bar_up_arrow);
4509 bar->dragging = -1; 4628 bar->dragging = -1;
4510 break; 4629 break;
4511 case GTK_SCROLL_STEP_FORWARD: 4630 case GTK_SCROLL_STEP_FORWARD:
4512 part = scroll_bar_down_arrow; 4631 part = (bar->horizontal
4632 ? scroll_bar_right_arrow : scroll_bar_down_arrow);
4513 bar->dragging = -1; 4633 bar->dragging = -1;
4514 break; 4634 break;
4515 case GTK_SCROLL_PAGE_BACKWARD: 4635 case GTK_SCROLL_PAGE_BACKWARD:
4516 part = scroll_bar_above_handle; 4636 part = (bar->horizontal
4637 ? scroll_bar_before_handle : scroll_bar_above_handle);
4517 bar->dragging = -1; 4638 bar->dragging = -1;
4518 break; 4639 break;
4519 case GTK_SCROLL_PAGE_FORWARD: 4640 case GTK_SCROLL_PAGE_FORWARD:
4520 part = scroll_bar_below_handle; 4641 part = (bar->horizontal
4642 ? scroll_bar_after_handle : scroll_bar_below_handle);
4521 bar->dragging = -1; 4643 bar->dragging = -1;
4522 break; 4644 break;
4523 } 4645 }
@@ -4525,7 +4647,7 @@ xg_scroll_callback (GtkRange *range,
4525 if (part >= 0) 4647 if (part >= 0)
4526 { 4648 {
4527 window_being_scrolled = bar->window; 4649 window_being_scrolled = bar->window;
4528 x_send_scroll_bar_event (bar->window, part, portion, whole); 4650 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
4529 } 4651 }
4530 4652
4531 return FALSE; 4653 return FALSE;
@@ -4543,7 +4665,7 @@ xg_end_scroll_callback (GtkWidget *widget,
4543 if (WINDOWP (window_being_scrolled)) 4665 if (WINDOWP (window_being_scrolled))
4544 { 4666 {
4545 x_send_scroll_bar_event (window_being_scrolled, 4667 x_send_scroll_bar_event (window_being_scrolled,
4546 scroll_bar_end_scroll, 0, 0); 4668 scroll_bar_end_scroll, 0, 0, bar->horizontal);
4547 window_being_scrolled = Qnil; 4669 window_being_scrolled = Qnil;
4548 } 4670 }
4549 4671
@@ -4567,29 +4689,27 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4567 float shown; 4689 float shown;
4568 int whole, portion, height; 4690 int whole, portion, height;
4569 enum scroll_bar_part part; 4691 enum scroll_bar_part part;
4692 int horizontal = bar->horizontal;
4570 4693
4571 /* Get the size of the thumb, a value between 0 and 1. */ 4694 /* Get the size of the thumb, a value between 0 and 1. */
4572 block_input (); 4695 block_input ();
4573 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL); 4696 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
4574 unblock_input (); 4697 unblock_input ();
4575 4698
4576 whole = 10000000; 4699 if (horizontal)
4577 portion = shown < 1 ? top * whole : 0; 4700 {
4578 4701 whole = bar->whole;
4579 if (shown < 1 && (eabs (top + shown - 1) < 1.0f / height)) 4702 portion = (top * (whole - (shown * whole))) / (1 - shown);
4580 /* Some derivatives of Xaw refuse to shrink the thumb when you reach 4703 portion = max (0, portion);
4581 the bottom, so we force the scrolling whenever we see that we're 4704 part = scroll_bar_horizontal_handle;
4582 too close to the bottom (in x_set_toolkit_scroll_bar_thumb 4705 }
4583 we try to ensure that we always stay two pixels away from the
4584 bottom). */
4585 part = scroll_bar_down_arrow;
4586 else 4706 else
4587 part = scroll_bar_handle; 4707 part = scroll_bar_handle;
4588 4708
4589 window_being_scrolled = bar->window; 4709 window_being_scrolled = bar->window;
4590 bar->dragging = portion; 4710 bar->dragging = portion;
4591 bar->last_seen_part = part; 4711 bar->last_seen_part = part;
4592 x_send_scroll_bar_event (bar->window, part, portion, whole); 4712 x_send_scroll_bar_event (bar->window, part, portion, whole, bar->horizontal);
4593} 4713}
4594 4714
4595 4715
@@ -4628,12 +4748,13 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
4628 window_being_scrolled = bar->window; 4748 window_being_scrolled = bar->window;
4629 bar->dragging = -1; 4749 bar->dragging = -1;
4630 bar->last_seen_part = part; 4750 bar->last_seen_part = part;
4631 x_send_scroll_bar_event (bar->window, part, position, height); 4751 x_send_scroll_bar_event (bar->window, part, position, height, bar->horizontal);
4632} 4752}
4633 4753
4634#endif /* not USE_GTK and not USE_MOTIF */ 4754#endif /* not USE_GTK and not USE_MOTIF */
4635 4755
4636#define SCROLL_BAR_NAME "verticalScrollBar" 4756#define SCROLL_BAR_NAME "verticalScrollBar"
4757#define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
4637 4758
4638/* Create the widget for scroll bar BAR on frame F. Record the widget 4759/* Create the widget for scroll bar BAR on frame F. Record the widget
4639 and X window of the scroll bar in BAR. */ 4760 and X window of the scroll bar in BAR. */
@@ -4651,6 +4772,18 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4651 unblock_input (); 4772 unblock_input ();
4652} 4773}
4653 4774
4775static void
4776x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4777{
4778 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
4779
4780 block_input ();
4781 xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4782 G_CALLBACK (xg_end_scroll_callback),
4783 scroll_bar_name);
4784 unblock_input ();
4785}
4786
4654#else /* not USE_GTK */ 4787#else /* not USE_GTK */
4655 4788
4656static void 4789static void
@@ -4846,6 +4979,208 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4846 SET_SCROLL_BAR_X_WIDGET (bar, widget); 4979 SET_SCROLL_BAR_X_WIDGET (bar, widget);
4847 xwindow = XtWindow (widget); 4980 xwindow = XtWindow (widget);
4848 bar->x_window = xwindow; 4981 bar->x_window = xwindow;
4982 bar->whole = 1;
4983 bar->horizontal = 0;
4984
4985 unblock_input ();
4986}
4987
4988static void
4989x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
4990{
4991 Window xwindow;
4992 Widget widget;
4993 Arg av[20];
4994 int ac = 0;
4995 const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
4996 unsigned long pixel;
4997
4998 block_input ();
4999
5000#ifdef USE_MOTIF
5001 /* Set resources. Create the widget. */
5002 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
5003 XtSetArg (av[ac], XmNminimum, 0); ++ac;
5004 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
5005 XtSetArg (av[ac], XmNorientation, XmHORIZONTAL); ++ac;
5006 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_RIGHT), ++ac;
5007 XtSetArg (av[ac], XmNincrement, 1); ++ac;
5008 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
5009
5010 pixel = f->output_data.x->scroll_bar_foreground_pixel;
5011 if (pixel != -1)
5012 {
5013 XtSetArg (av[ac], XmNforeground, pixel);
5014 ++ac;
5015 }
5016
5017 pixel = f->output_data.x->scroll_bar_background_pixel;
5018 if (pixel != -1)
5019 {
5020 XtSetArg (av[ac], XmNbackground, pixel);
5021 ++ac;
5022 }
5023
5024 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
5025 (char *) scroll_bar_name, av, ac);
5026
5027 /* Add one callback for everything that can happen. */
5028 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
5029 (XtPointer) bar);
5030 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
5031 (XtPointer) bar);
5032 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
5033 (XtPointer) bar);
5034 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
5035 (XtPointer) bar);
5036 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
5037 (XtPointer) bar);
5038 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
5039 (XtPointer) bar);
5040 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
5041 (XtPointer) bar);
5042
5043 /* Realize the widget. Only after that is the X window created. */
5044 XtRealizeWidget (widget);
5045
5046 /* Set the cursor to an arrow. I didn't find a resource to do that.
5047 And I'm wondering why it hasn't an arrow cursor by default. */
5048 XDefineCursor (XtDisplay (widget), XtWindow (widget),
5049 f->output_data.x->nontext_cursor);
5050
5051#else /* !USE_MOTIF i.e. use Xaw */
5052
5053 /* Set resources. Create the widget. The background of the
5054 Xaw3d scroll bar widget is a little bit light for my taste.
5055 We don't alter it here to let users change it according
5056 to their taste with `emacs*verticalScrollBar.background: xxx'. */
5057 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
5058 XtSetArg (av[ac], XtNorientation, XtorientHorizontal); ++ac;
5059 /* For smoother scrolling with Xaw3d -sm */
5060 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
5061
5062 pixel = f->output_data.x->scroll_bar_foreground_pixel;
5063 if (pixel != -1)
5064 {
5065 XtSetArg (av[ac], XtNforeground, pixel);
5066 ++ac;
5067 }
5068
5069 pixel = f->output_data.x->scroll_bar_background_pixel;
5070 if (pixel != -1)
5071 {
5072 XtSetArg (av[ac], XtNbackground, pixel);
5073 ++ac;
5074 }
5075
5076 /* Top/bottom shadow colors. */
5077
5078 /* Allocate them, if necessary. */
5079 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
5080 {
5081 pixel = f->output_data.x->scroll_bar_background_pixel;
5082 if (pixel != -1)
5083 {
5084 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
5085 FRAME_X_COLORMAP (f),
5086 &pixel, 1.2, 0x8000))
5087 pixel = -1;
5088 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
5089 }
5090 }
5091 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
5092 {
5093 pixel = f->output_data.x->scroll_bar_background_pixel;
5094 if (pixel != -1)
5095 {
5096 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
5097 FRAME_X_COLORMAP (f),
5098 &pixel, 0.6, 0x4000))
5099 pixel = -1;
5100 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
5101 }
5102 }
5103
5104#ifdef XtNbeNiceToColormap
5105 /* Tell the toolkit about them. */
5106 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
5107 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
5108 /* We tried to allocate a color for the top/bottom shadow, and
5109 failed, so tell Xaw3d to use dithering instead. */
5110 /* But only if we have a small colormap. Xaw3d can allocate nice
5111 colors itself. */
5112 {
5113 XtSetArg (av[ac], XtNbeNiceToColormap,
5114 DefaultDepthOfScreen (FRAME_X_SCREEN (f)) < 16);
5115 ++ac;
5116 }
5117 else
5118 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
5119 be more consistent with other emacs 3d colors, and since Xaw3d is
5120 not good at dealing with allocation failure. */
5121 {
5122 /* This tells Xaw3d to use real colors instead of dithering for
5123 the shadows. */
5124 XtSetArg (av[ac], XtNbeNiceToColormap, False);
5125 ++ac;
5126
5127 /* Specify the colors. */
5128 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
5129 if (pixel != -1)
5130 {
5131 XtSetArg (av[ac], XtNtopShadowPixel, pixel);
5132 ++ac;
5133 }
5134 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
5135 if (pixel != -1)
5136 {
5137 XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
5138 ++ac;
5139 }
5140 }
5141#endif
5142
5143 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
5144 f->output_data.x->edit_widget, av, ac);
5145
5146 {
5147 char const *initial = "";
5148 char const *val = initial;
5149 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
5150#ifdef XtNarrowScrollbars
5151 XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
5152#endif
5153 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
5154 if (xaw3d_arrow_scroll || val == initial)
5155 { /* ARROW_SCROLL */
5156 xaw3d_arrow_scroll = True;
5157 /* Isn't that just a personal preference ? --Stef */
5158 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
5159 }
5160 }
5161
5162 /* Define callbacks. */
5163 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
5164 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
5165 (XtPointer) bar);
5166
5167 /* Realize the widget. Only after that is the X window created. */
5168 XtRealizeWidget (widget);
5169
5170#endif /* !USE_MOTIF */
5171
5172 /* Install an action hook that lets us detect when the user
5173 finishes interacting with a scroll bar. */
5174 if (horizontal_action_hook_id == 0)
5175 horizontal_action_hook_id
5176 = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0);
5177
5178 /* Remember X window and widget in the scroll bar vector. */
5179 SET_SCROLL_BAR_X_WIDGET (bar, widget);
5180 xwindow = XtWindow (widget);
5181 bar->x_window = xwindow;
5182 bar->whole = 1;
5183 bar->horizontal = 1;
4849 5184
4850 unblock_input (); 5185 unblock_input ();
4851} 5186}
@@ -4862,6 +5197,12 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
4862 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); 5197 xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4863} 5198}
4864 5199
5200static void
5201x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole)
5202{
5203 xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
5204}
5205
4865#else /* not USE_GTK */ 5206#else /* not USE_GTK */
4866static void 5207static void
4867x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, 5208x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
@@ -4974,6 +5315,89 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
4974 5315
4975 unblock_input (); 5316 unblock_input ();
4976} 5317}
5318
5319static void
5320x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position,
5321 int whole)
5322{
5323 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5324 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
5325 float top, shown;
5326
5327 block_input ();
5328
5329#ifdef USE_MOTIF
5330 bar->whole = whole;
5331 shown = (float) portion / whole;
5332 top = (float) position / (whole - portion);
5333 {
5334 int size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
5335 int value = clip_to_bounds (0, top * (XM_SB_MAX - size), XM_SB_MAX - size);
5336
5337 XmScrollBarSetValues (widget, value, size, 0, 0, False);
5338 }
5339#else /* !USE_MOTIF i.e. use Xaw */
5340 bar->whole = whole;
5341 if (whole == 0)
5342 top = 0, shown = 1;
5343 else
5344 {
5345 top = (float) position / whole;
5346 shown = (float) portion / whole;
5347 }
5348
5349 {
5350 float old_top, old_shown;
5351 Dimension height;
5352 XtVaGetValues (widget,
5353 XtNtopOfThumb, &old_top,
5354 XtNshown, &old_shown,
5355 XtNheight, &height,
5356 NULL);
5357
5358#if 0
5359 /* Massage the top+shown values. */
5360 if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
5361 top = max (0, min (1, top));
5362 else
5363 top = old_top;
5364#if ! defined (HAVE_XAW3D)
5365 /* With Xaw, 'top' values too closer to 1.0 may
5366 cause the thumb to disappear. Fix that. */
5367 top = min (top, 0.99f);
5368#endif
5369 /* Keep two pixels available for moving the thumb down. */
5370 shown = max (0, min (1 - top - (2.0f / height), shown));
5371#if ! defined (HAVE_XAW3D)
5372 /* Likewise with too small 'shown'. */
5373 shown = max (shown, 0.01f);
5374#endif
5375#endif
5376
5377 /* If the call to XawScrollbarSetThumb below doesn't seem to
5378 work, check that 'NARROWPROTO' is defined in src/config.h.
5379 If this is not so, most likely you need to fix configure. */
5380 XawScrollbarSetThumb (widget, top, shown);
5381#if 0
5382 if (top != old_top || shown != old_shown)
5383 {
5384 if (bar->dragging == -1)
5385 XawScrollbarSetThumb (widget, top, shown);
5386 else
5387 {
5388 /* Try to make the scrolling a tad smoother. */
5389 if (!xaw3d_pick_top)
5390 shown = min (shown, old_shown);
5391
5392 XawScrollbarSetThumb (widget, top, shown);
5393 }
5394 }
5395#endif
5396 }
5397#endif /* !USE_MOTIF */
5398
5399 unblock_input ();
5400}
4977#endif /* not USE_GTK */ 5401#endif /* not USE_GTK */
4978 5402
4979#endif /* USE_TOOLKIT_SCROLL_BARS */ 5403#endif /* USE_TOOLKIT_SCROLL_BARS */
@@ -4990,7 +5414,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
4990 scroll bar. */ 5414 scroll bar. */
4991 5415
4992static struct scroll_bar * 5416static struct scroll_bar *
4993x_scroll_bar_create (struct window *w, int top, int left, int width, int height) 5417x_scroll_bar_create (struct window *w, int top, int left, int width, int height, bool horizontal)
4994{ 5418{
4995 struct frame *f = XFRAME (w->frame); 5419 struct frame *f = XFRAME (w->frame);
4996 struct scroll_bar *bar 5420 struct scroll_bar *bar
@@ -5000,7 +5424,10 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
5000 block_input (); 5424 block_input ();
5001 5425
5002#ifdef USE_TOOLKIT_SCROLL_BARS 5426#ifdef USE_TOOLKIT_SCROLL_BARS
5003 x_create_toolkit_scroll_bar (f, bar); 5427 if (horizontal)
5428 x_create_horizontal_toolkit_scroll_bar (f, bar);
5429 else
5430 x_create_toolkit_scroll_bar (f, bar);
5004#else /* not USE_TOOLKIT_SCROLL_BARS */ 5431#else /* not USE_TOOLKIT_SCROLL_BARS */
5005 { 5432 {
5006 XSetWindowAttributes a; 5433 XSetWindowAttributes a;
@@ -5063,8 +5490,12 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
5063#ifdef USE_TOOLKIT_SCROLL_BARS 5490#ifdef USE_TOOLKIT_SCROLL_BARS
5064 { 5491 {
5065#ifdef USE_GTK 5492#ifdef USE_GTK
5066 xg_update_scrollbar_pos (f, bar->x_window, top, 5493 if (horizontal)
5067 left,width, max (height, 1)); 5494 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
5495 left, width, max (height, 1));
5496 else
5497 xg_update_scrollbar_pos (f, bar->x_window, top,
5498 left, width, max (height, 1));
5068#else /* not USE_GTK */ 5499#else /* not USE_GTK */
5069 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); 5500 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
5070 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); 5501 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
@@ -5148,7 +5579,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
5148 5579
5149 /* Draw the empty space above the handle. Note that we can't clear 5580 /* Draw the empty space above the handle. Note that we can't clear
5150 zero-height areas; that means "clear to end of window." */ 5581 zero-height areas; that means "clear to end of window." */
5151 if (start > 0) 5582 if ((inside_width > 0) && (start > 0))
5152 x_clear_area (FRAME_X_DISPLAY (f), w, 5583 x_clear_area (FRAME_X_DISPLAY (f), w,
5153 VERTICAL_SCROLL_BAR_LEFT_BORDER, 5584 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5154 VERTICAL_SCROLL_BAR_TOP_BORDER, 5585 VERTICAL_SCROLL_BAR_TOP_BORDER,
@@ -5173,7 +5604,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
5173 5604
5174 /* Draw the empty space below the handle. Note that we can't 5605 /* Draw the empty space below the handle. Note that we can't
5175 clear zero-height areas; that means "clear to end of window." */ 5606 clear zero-height areas; that means "clear to end of window." */
5176 if (end < inside_height) 5607 if ((inside_width > 0) && (end < inside_height))
5177 x_clear_area (FRAME_X_DISPLAY (f), w, 5608 x_clear_area (FRAME_X_DISPLAY (f), w,
5178 VERTICAL_SCROLL_BAR_LEFT_BORDER, 5609 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5179 VERTICAL_SCROLL_BAR_TOP_BORDER + end, 5610 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
@@ -5205,7 +5636,10 @@ x_scroll_bar_remove (struct scroll_bar *bar)
5205#endif 5636#endif
5206 5637
5207 /* Dissociate this scroll bar from its window. */ 5638 /* Dissociate this scroll bar from its window. */
5208 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); 5639 if (bar->horizontal)
5640 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
5641 else
5642 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
5209 5643
5210 unblock_input (); 5644 unblock_input ();
5211} 5645}
@@ -5229,8 +5663,6 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5229 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); 5663 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
5230 top = window_y; 5664 top = window_y;
5231 height = window_height; 5665 height = window_height;
5232
5233 /* Compute the left edge and the width of the scroll bar area. */
5234 left = WINDOW_SCROLL_BAR_AREA_X (w); 5666 left = WINDOW_SCROLL_BAR_AREA_X (w);
5235 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); 5667 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
5236 5668
@@ -5245,7 +5677,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5245 unblock_input (); 5677 unblock_input ();
5246 } 5678 }
5247 5679
5248 bar = x_scroll_bar_create (w, top, left, width, max (height, 1)); 5680 bar = x_scroll_bar_create (w, top, left, width, max (height, 1), 0);
5249 } 5681 }
5250 else 5682 else
5251 { 5683 {
@@ -5334,6 +5766,138 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5334} 5766}
5335 5767
5336 5768
5769static void
5770XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
5771{
5772 struct frame *f = XFRAME (w->frame);
5773 Lisp_Object barobj;
5774 struct scroll_bar *bar;
5775 int top, height, left, width;
5776 int window_x, window_width;
5777 int pixel_width = WINDOW_PIXEL_WIDTH (w);
5778
5779 /* Get window dimensions. */
5780 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
5781 left = window_x;
5782 width = window_width;
5783 top = WINDOW_SCROLL_BAR_AREA_Y (w);
5784 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
5785
5786 /* Does the scroll bar exist yet? */
5787 if (NILP (w->horizontal_scroll_bar))
5788 {
5789 if (width > 0 && height > 0)
5790 {
5791 block_input ();
5792
5793 /* Clear also part between window_width and
5794 WINDOW_PIXEL_WIDTH. */
5795 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5796 left, top, pixel_width, height);
5797 unblock_input ();
5798 }
5799
5800 bar = x_scroll_bar_create (w, top, left, width, height, 1);
5801 }
5802 else
5803 {
5804 /* It may just need to be moved and resized. */
5805 unsigned int mask = 0;
5806
5807 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
5808
5809 block_input ();
5810
5811 if (left != bar->left)
5812 mask |= CWX;
5813 if (top != bar->top)
5814 mask |= CWY;
5815 if (width != bar->width)
5816 mask |= CWWidth;
5817 if (height != bar->height)
5818 mask |= CWHeight;
5819
5820#ifdef USE_TOOLKIT_SCROLL_BARS
5821 /* Move/size the scroll bar widget. */
5822 if (mask)
5823 {
5824 /* Since toolkit scroll bars are smaller than the space reserved
5825 for them on the frame, we have to clear "under" them. */
5826 if (width > 0 && height > 0)
5827 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5828 WINDOW_LEFT_EDGE_X (w), top,
5829 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
5830#ifdef USE_GTK
5831 xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
5832 width, height);
5833#else /* not USE_GTK */
5834 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5835 left, top, width, height, 0);
5836#endif /* not USE_GTK */
5837 }
5838#else /* not USE_TOOLKIT_SCROLL_BARS */
5839
5840 /* Clear areas not covered by the scroll bar because it's not as
5841 wide as the area reserved for it. This makes sure a
5842 previous mode line display is cleared after C-x 2 C-x 1, for
5843 example. */
5844 {
5845 int area_height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
5846 int rest = area_height - height;
5847 if (rest > 0 && width > 0)
5848 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5849 left, top, width, rest);
5850 }
5851
5852 /* Move/size the scroll bar window. */
5853 if (mask)
5854 {
5855 XWindowChanges wc;
5856
5857 wc.x = left;
5858 wc.y = top;
5859 wc.width = width;
5860 wc.height = height;
5861 XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
5862 mask, &wc);
5863 }
5864
5865#endif /* not USE_TOOLKIT_SCROLL_BARS */
5866
5867 /* Remember new settings. */
5868 bar->left = left;
5869 bar->top = top;
5870 bar->width = width;
5871 bar->height = height;
5872
5873 unblock_input ();
5874 }
5875
5876#ifdef USE_TOOLKIT_SCROLL_BARS
5877 x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
5878#else /* not USE_TOOLKIT_SCROLL_BARS */
5879 /* Set the scroll bar's current state, unless we're currently being
5880 dragged. */
5881 if (bar->dragging == -1)
5882 {
5883 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width);
5884
5885 if (whole == 0)
5886 x_scroll_bar_set_handle (bar, 0, left_range, 0);
5887 else
5888 {
5889 int start = ((double) position * left_range) / whole;
5890 int end = ((double) (position + portion) * left_range) / whole;
5891 x_scroll_bar_set_handle (bar, start, end, 0);
5892 }
5893 }
5894#endif /* not USE_TOOLKIT_SCROLL_BARS */
5895
5896 XSETVECTOR (barobj, bar);
5897 wset_horizontal_scroll_bar (w, barobj);
5898}
5899
5900
5337/* The following three hooks are used when we're doing a thorough 5901/* The following three hooks are used when we're doing a thorough
5338 redisplay of the frame. We don't explicitly know which scroll bars 5902 redisplay of the frame. We don't explicitly know which scroll bars
5339 are going to be deleted, because keeping track of when windows go 5903 are going to be deleted, because keeping track of when windows go
@@ -5349,17 +5913,22 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5349static void 5913static void
5350XTcondemn_scroll_bars (struct frame *frame) 5914XTcondemn_scroll_bars (struct frame *frame)
5351{ 5915{
5352 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ 5916 if (!NILP (FRAME_SCROLL_BARS (frame)))
5353 while (! NILP (FRAME_SCROLL_BARS (frame)))
5354 { 5917 {
5355 Lisp_Object bar; 5918 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5356 bar = FRAME_SCROLL_BARS (frame); 5919 {
5357 fset_scroll_bars (frame, XSCROLL_BAR (bar)->next); 5920 /* Prepend scrollbars to already condemned ones. */
5358 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); 5921 Lisp_Object last = FRAME_SCROLL_BARS (frame);
5359 XSCROLL_BAR (bar)->prev = Qnil; 5922
5360 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) 5923 while (!NILP (XSCROLL_BAR (last)->next))
5361 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; 5924 last = XSCROLL_BAR (last)->next;
5362 fset_condemned_scroll_bars (frame, bar); 5925
5926 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5927 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
5928 }
5929
5930 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
5931 fset_scroll_bars (frame, Qnil);
5363 } 5932 }
5364} 5933}
5365 5934
@@ -5368,47 +5937,84 @@ XTcondemn_scroll_bars (struct frame *frame)
5368 Note that WINDOW isn't necessarily condemned at all. */ 5937 Note that WINDOW isn't necessarily condemned at all. */
5369 5938
5370static void 5939static void
5371XTredeem_scroll_bar (struct window *window) 5940XTredeem_scroll_bar (struct window *w)
5372{ 5941{
5373 struct scroll_bar *bar; 5942 struct scroll_bar *bar;
5374 struct frame *f;
5375 Lisp_Object barobj; 5943 Lisp_Object barobj;
5944 struct frame *f;
5376 5945
5377 /* We can't redeem this window's scroll bar if it doesn't have one. */ 5946 /* We can't redeem this window's scroll bar if it doesn't have one. */
5378 if (NILP (window->vertical_scroll_bar)) 5947 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
5379 emacs_abort (); 5948 emacs_abort ();
5380 5949
5381 bar = XSCROLL_BAR (window->vertical_scroll_bar); 5950 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
5382
5383 /* Unlink it from the condemned list. */
5384 f = XFRAME (WINDOW_FRAME (window));
5385 if (NILP (bar->prev))
5386 { 5951 {
5387 /* If the prev pointer is nil, it must be the first in one of 5952 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5388 the lists. */ 5953 /* Unlink it from the condemned list. */
5389 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar)) 5954 f = XFRAME (WINDOW_FRAME (w));
5390 /* It's not condemned. Everything's fine. */ 5955 if (NILP (bar->prev))
5391 return; 5956 {
5392 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), 5957 /* If the prev pointer is nil, it must be the first in one of
5393 window->vertical_scroll_bar)) 5958 the lists. */
5394 fset_condemned_scroll_bars (f, bar->next); 5959 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
5960 /* It's not condemned. Everything's fine. */
5961 goto horizontal;
5962 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5963 w->vertical_scroll_bar))
5964 fset_condemned_scroll_bars (f, bar->next);
5965 else
5966 /* If its prev pointer is nil, it must be at the front of
5967 one or the other! */
5968 emacs_abort ();
5969 }
5395 else 5970 else
5396 /* If its prev pointer is nil, it must be at the front of 5971 XSCROLL_BAR (bar->prev)->next = bar->next;
5397 one or the other! */ 5972
5398 emacs_abort (); 5973 if (! NILP (bar->next))
5974 XSCROLL_BAR (bar->next)->prev = bar->prev;
5975
5976 bar->next = FRAME_SCROLL_BARS (f);
5977 bar->prev = Qnil;
5978 XSETVECTOR (barobj, bar);
5979 fset_scroll_bars (f, barobj);
5980 if (! NILP (bar->next))
5981 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5399 } 5982 }
5400 else
5401 XSCROLL_BAR (bar->prev)->next = bar->next;
5402 5983
5403 if (! NILP (bar->next)) 5984 horizontal:
5404 XSCROLL_BAR (bar->next)->prev = bar->prev; 5985 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
5986 {
5987 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
5988 /* Unlink it from the condemned list. */
5989 f = XFRAME (WINDOW_FRAME (w));
5990 if (NILP (bar->prev))
5991 {
5992 /* If the prev pointer is nil, it must be the first in one of
5993 the lists. */
5994 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
5995 /* It's not condemned. Everything's fine. */
5996 return;
5997 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5998 w->horizontal_scroll_bar))
5999 fset_condemned_scroll_bars (f, bar->next);
6000 else
6001 /* If its prev pointer is nil, it must be at the front of
6002 one or the other! */
6003 emacs_abort ();
6004 }
6005 else
6006 XSCROLL_BAR (bar->prev)->next = bar->next;
5405 6007
5406 bar->next = FRAME_SCROLL_BARS (f); 6008 if (! NILP (bar->next))
5407 bar->prev = Qnil; 6009 XSCROLL_BAR (bar->next)->prev = bar->prev;
5408 XSETVECTOR (barobj, bar); 6010
5409 fset_scroll_bars (f, barobj); 6011 bar->next = FRAME_SCROLL_BARS (f);
5410 if (! NILP (bar->next)) 6012 bar->prev = Qnil;
5411 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); 6013 XSETVECTOR (barobj, bar);
6014 fset_scroll_bars (f, barobj);
6015 if (! NILP (bar->next))
6016 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
6017 }
5412} 6018}
5413 6019
5414/* Remove all scroll bars on FRAME that haven't been saved since the 6020/* Remove all scroll bars on FRAME that haven't been saved since the
@@ -5493,7 +6099,9 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
5493 if (! WINDOWP (bar->window)) 6099 if (! WINDOWP (bar->window))
5494 emacs_abort (); 6100 emacs_abort ();
5495 6101
5496 emacs_event->kind = SCROLL_BAR_CLICK_EVENT; 6102 emacs_event->kind = (bar->horizontal
6103 ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
6104 : SCROLL_BAR_CLICK_EVENT);
5497 emacs_event->code = event->xbutton.button - Button1; 6105 emacs_event->code = event->xbutton.button - Button1;
5498 emacs_event->modifiers 6106 emacs_event->modifiers
5499 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO 6107 = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
@@ -5505,36 +6113,68 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
5505 emacs_event->frame_or_window = bar->window; 6113 emacs_event->frame_or_window = bar->window;
5506 emacs_event->arg = Qnil; 6114 emacs_event->arg = Qnil;
5507 emacs_event->timestamp = event->xbutton.time; 6115 emacs_event->timestamp = event->xbutton.time;
5508 { 6116 if (bar->horizontal)
5509 int top_range 6117 {
5510 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height); 6118 int left_range
5511 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER; 6119 = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
6120 int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
5512 6121
5513 if (y < 0) y = 0; 6122 if (x < 0) x = 0;
5514 if (y > top_range) y = top_range; 6123 if (x > left_range) x = left_range;
5515 6124
5516 if (y < bar->start) 6125 if (x < bar->start)
5517 emacs_event->part = scroll_bar_above_handle; 6126 emacs_event->part = scroll_bar_before_handle;
5518 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE) 6127 else if (x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
5519 emacs_event->part = scroll_bar_handle; 6128 emacs_event->part = scroll_bar_horizontal_handle;
5520 else 6129 else
5521 emacs_event->part = scroll_bar_below_handle; 6130 emacs_event->part = scroll_bar_after_handle;
5522 6131
5523#ifndef USE_TOOLKIT_SCROLL_BARS 6132#ifndef USE_TOOLKIT_SCROLL_BARS
5524 /* If the user has released the handle, set it to its final position. */ 6133 /* If the user has released the handle, set it to its final position. */
5525 if (event->type == ButtonRelease && bar->dragging != -1) 6134 if (event->type == ButtonRelease && bar->dragging != -1)
5526 { 6135 {
5527 int new_start = y - bar->dragging; 6136 int new_start = - bar->dragging;
5528 int new_end = new_start + bar->end - bar->start; 6137 int new_end = new_start + bar->end - bar->start;
5529 6138
5530 x_scroll_bar_set_handle (bar, new_start, new_end, 0); 6139 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5531 bar->dragging = -1; 6140 bar->dragging = -1;
5532 } 6141 }
5533#endif 6142#endif
5534 6143
5535 XSETINT (emacs_event->x, y); 6144 XSETINT (emacs_event->x, left_range);
5536 XSETINT (emacs_event->y, top_range); 6145 XSETINT (emacs_event->y, x);
5537 } 6146 }
6147 else
6148 {
6149 int top_range
6150 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
6151 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
6152
6153 if (y < 0) y = 0;
6154 if (y > top_range) y = top_range;
6155
6156 if (y < bar->start)
6157 emacs_event->part = scroll_bar_above_handle;
6158 else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
6159 emacs_event->part = scroll_bar_handle;
6160 else
6161 emacs_event->part = scroll_bar_below_handle;
6162
6163#ifndef USE_TOOLKIT_SCROLL_BARS
6164 /* If the user has released the handle, set it to its final position. */
6165 if (event->type == ButtonRelease && bar->dragging != -1)
6166 {
6167 int new_start = y - bar->dragging;
6168 int new_end = new_start + bar->end - bar->start;
6169
6170 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
6171 bar->dragging = -1;
6172 }
6173#endif
6174
6175 XSETINT (emacs_event->x, y);
6176 XSETINT (emacs_event->y, top_range);
6177 }
5538} 6178}
5539 6179
5540#ifndef USE_TOOLKIT_SCROLL_BARS 6180#ifndef USE_TOOLKIT_SCROLL_BARS
@@ -5641,6 +6281,75 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
5641} 6281}
5642 6282
5643 6283
6284/* Return information to the user about the current position of the mouse
6285 on the scroll bar. */
6286
6287static void
6288x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
6289 enum scroll_bar_part *part, Lisp_Object *x,
6290 Lisp_Object *y, Time *timestamp)
6291{
6292 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
6293 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
6294 Window w = bar->x_window;
6295 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6296 int win_x, win_y;
6297 Window dummy_window;
6298 int dummy_coord;
6299 unsigned int dummy_mask;
6300
6301 block_input ();
6302
6303 /* Get the mouse's position relative to the scroll bar window, and
6304 report that. */
6305 if (XQueryPointer (FRAME_X_DISPLAY (f), w,
6306
6307 /* Root, child, root x and root y. */
6308 &dummy_window, &dummy_window,
6309 &dummy_coord, &dummy_coord,
6310
6311 /* Position relative to scroll bar. */
6312 &win_x, &win_y,
6313
6314 /* Mouse buttons and modifier keys. */
6315 &dummy_mask))
6316 {
6317 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
6318
6319 win_x -= HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
6320
6321 if (bar->dragging != -1)
6322 win_x -= bar->dragging;
6323
6324 if (win_x < 0)
6325 win_x = 0;
6326 if (win_x > left_range)
6327 win_x = left_range;
6328
6329 *fp = f;
6330 *bar_window = bar->window;
6331
6332 if (bar->dragging != -1)
6333 *part = scroll_bar_horizontal_handle;
6334 else if (win_x < bar->start)
6335 *part = scroll_bar_before_handle;
6336 else if (win_x < bar->end + HORIZONTAL_SCROLL_BAR_MIN_HANDLE)
6337 *part = scroll_bar_handle;
6338 else
6339 *part = scroll_bar_after_handle;
6340
6341 XSETINT (*y, win_x);
6342 XSETINT (*x, left_range);
6343
6344 f->mouse_moved = 0;
6345 dpyinfo->last_mouse_scroll_bar = NULL;
6346 *timestamp = dpyinfo->last_mouse_movement_time;
6347 }
6348
6349 unblock_input ();
6350}
6351
6352
5644/* The screen has been cleared so we may have changed foreground or 6353/* The screen has been cleared so we may have changed foreground or
5645 background colors, and the scroll bars may need to be redrawn. 6354 background colors, and the scroll bars may need to be redrawn.
5646 Clear out the scroll bars, and ask for expose events, so we can 6355 Clear out the scroll bars, and ask for expose events, so we can
@@ -5783,6 +6492,35 @@ static void xembed_send_message (struct frame *f, Time,
5783 enum xembed_message, 6492 enum xembed_message,
5784 long detail, long data1, long data2); 6493 long detail, long data1, long data2);
5785 6494
6495static void
6496x_net_wm_state (struct frame *f, Window window)
6497{
6498 int value = FULLSCREEN_NONE;
6499 Lisp_Object lval = Qnil;
6500 int sticky = 0;
6501
6502 (void)get_current_wm_state (f, window, &value, &sticky);
6503
6504 switch (value)
6505 {
6506 case FULLSCREEN_WIDTH:
6507 lval = Qfullwidth;
6508 break;
6509 case FULLSCREEN_HEIGHT:
6510 lval = Qfullheight;
6511 break;
6512 case FULLSCREEN_BOTH:
6513 lval = Qfullboth;
6514 break;
6515 case FULLSCREEN_MAXIMIZED:
6516 lval = Qmaximized;
6517 break;
6518 }
6519
6520 store_frame_param (f, Qfullscreen, lval);
6521/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
6522}
6523
5786/* Handles the XEvent EVENT on display DPYINFO. 6524/* Handles the XEvent EVENT on display DPYINFO.
5787 6525
5788 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. 6526 *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@@ -5980,6 +6718,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
5980 *finish = X_EVENT_GOTO_OUT; 6718 *finish = X_EVENT_GOTO_OUT;
5981 goto done; 6719 goto done;
5982 } 6720 }
6721 else if (event->xclient.message_type == dpyinfo->Xatom_Horizontal_Scrollbar)
6722 {
6723 x_horizontal_scroll_bar_to_input_event (event, &inev.ie);
6724 *finish = X_EVENT_GOTO_OUT;
6725 goto done;
6726 }
5983#endif /* USE_TOOLKIT_SCROLL_BARS */ 6727#endif /* USE_TOOLKIT_SCROLL_BARS */
5984 6728
5985 /* XEmbed messages from the embedder (if any). */ 6729 /* XEmbed messages from the embedder (if any). */
@@ -6131,7 +6875,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6131 goto OTHER; 6875 goto OTHER;
6132#else /* not USE_TOOLKIT_SCROLL_BARS */ 6876#else /* not USE_TOOLKIT_SCROLL_BARS */
6133 bar = x_window_to_scroll_bar (event->xexpose.display, 6877 bar = x_window_to_scroll_bar (event->xexpose.display,
6134 event->xexpose.window); 6878 event->xexpose.window, 2);
6135 6879
6136 if (bar) 6880 if (bar)
6137 x_scroll_bar_expose (bar, event); 6881 x_scroll_bar_expose (bar, event);
@@ -6695,7 +7439,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6695#ifndef USE_TOOLKIT_SCROLL_BARS 7439#ifndef USE_TOOLKIT_SCROLL_BARS
6696 struct scroll_bar *bar 7440 struct scroll_bar *bar
6697 = x_window_to_scroll_bar (event->xmotion.display, 7441 = x_window_to_scroll_bar (event->xmotion.display,
6698 event->xmotion.window); 7442 event->xmotion.window, 2);
6699 7443
6700 if (bar) 7444 if (bar)
6701 x_scroll_bar_note_movement (bar, &event->xmotion); 7445 x_scroll_bar_note_movement (bar, &event->xmotion);
@@ -6728,6 +7472,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6728#endif 7472#endif
6729 if (f) 7473 if (f)
6730 { 7474 {
7475 x_net_wm_state (f, event->xconfigure.window);
7476
6731#ifndef USE_X_TOOLKIT 7477#ifndef USE_X_TOOLKIT
6732#ifndef USE_GTK 7478#ifndef USE_GTK
6733 int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width); 7479 int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
@@ -6838,7 +7584,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6838 { 7584 {
6839 struct scroll_bar *bar 7585 struct scroll_bar *bar
6840 = x_window_to_scroll_bar (event->xbutton.display, 7586 = x_window_to_scroll_bar (event->xbutton.display,
6841 event->xbutton.window); 7587 event->xbutton.window, 2);
6842 7588
6843#ifdef USE_TOOLKIT_SCROLL_BARS 7589#ifdef USE_TOOLKIT_SCROLL_BARS
6844 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit 7590 /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
@@ -7824,10 +8570,10 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7824 FRAME_COLUMN_WIDTH (f) = font->average_width; 8570 FRAME_COLUMN_WIDTH (f) = font->average_width;
7825 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font); 8571 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
7826 8572
7827 FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); 8573#ifndef USE_X_TOOLKIT \
8574/** FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); **/
7828 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); 8575 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
7829 8576#endif
7830 compute_fringe_widths (f, 1);
7831 8577
7832 /* Compute character columns occupied by scrollbar. 8578 /* Compute character columns occupied by scrollbar.
7833 8579
@@ -8658,7 +9404,7 @@ x_wait_for_event (struct frame *f, int eventtype)
8658} 9404}
8659 9405
8660 9406
8661/* Change the size of frame F's X window to COLS/ROWS in the case F 9407/* Change the size of frame F's X window to WIDTH/HEIGHT in the case F
8662 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to 9408 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8663 top-left-corner window gravity for this size change and subsequent 9409 top-left-corner window gravity for this size change and subsequent
8664 size changes. Otherwise we leave the window gravity unchanged. */ 9410 size changes. Otherwise we leave the window gravity unchanged. */
@@ -8668,23 +9414,39 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height,
8668{ 9414{
8669 int pixelwidth, pixelheight; 9415 int pixelwidth, pixelheight;
8670 9416
8671 check_frame_size (f, &width, &height, pixelwise); 9417/** if (pixelwise) **/
8672 9418/** { **/
8673 compute_fringe_widths (f, 0); 9419/** pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); **/
8674 9420/** pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); **/
8675 pixelwidth = ((pixelwise 9421/** } **/
8676 ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width) 9422/** else **/
8677 : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width)) 9423/** { **/
8678 + FRAME_TOOLBAR_WIDTH (f)); 9424/** pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); **/
9425/** pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); **/
9426/** } **/
9427
9428/** FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOLBAR_HEIGHT (f); **/
9429 pixelwidth = (pixelwise
9430 ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
9431 : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width));
8679 pixelheight = ((pixelwise 9432 pixelheight = ((pixelwise
8680 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height) 9433 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
8681 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)) 9434 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)));
8682 + FRAME_MENUBAR_HEIGHT (f) 9435
8683 + FRAME_TOOLBAR_HEIGHT (f)); 9436/** pixelwidth = ((pixelwise ? width : (width * FRAME_COLUMN_WIDTH (f))) **/
9437/** + FRAME_SCROLL_BAR_AREA_WIDTH (f) **/
9438/** + FRAME_TOTAL_FRINGE_WIDTH (f) **/
9439/** + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
9440
9441/** pixelheight = ((pixelwise ? height : (height * FRAME_LINE_HEIGHT (f))) **/
9442/** + FRAME_TOOLBAR_HEIGHT (f) **/
9443/** + FRAME_SCROLL_BAR_AREA_HEIGHT (f) **/
9444/** + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
9445
8684 if (change_gravity) f->win_gravity = NorthWestGravity; 9446 if (change_gravity) f->win_gravity = NorthWestGravity;
8685 x_wm_set_size_hint (f, 0, 0); 9447 x_wm_set_size_hint (f, 0, 0);
8686 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 9448 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8687 pixelwidth, pixelheight); 9449 pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
8688 9450
8689 9451
8690 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to 9452 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
@@ -8714,7 +9476,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height,
8714 x_wait_for_event (f, ConfigureNotify); 9476 x_wait_for_event (f, ConfigureNotify);
8715 else 9477 else
8716 { 9478 {
8717 change_frame_size (f, width, height, 0, 1, 0, 1); 9479 change_frame_size (f, pixelwidth, pixelheight, 0, 1, 0, 1);
8718 x_sync (f); 9480 x_sync (f);
8719 } 9481 }
8720} 9482}
@@ -8730,8 +9492,9 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
8730{ 9492{
8731 block_input (); 9493 block_input ();
8732 9494
8733 check_frame_size (f, &width, &height, pixelwise); 9495 /* The following breaks our calculations. If it's really needed,
8734 9496 think of something else. */
9497#if 0
8735 if (NILP (tip_frame) || XFRAME (tip_frame) != f) 9498 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
8736 { 9499 {
8737 int text_width, text_height; 9500 int text_width, text_height;
@@ -8754,6 +9517,7 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
8754 9517
8755 change_frame_size (f, text_width, text_height, 0, 1, 0, 1); 9518 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
8756 } 9519 }
9520#endif
8757 9521
8758#ifdef USE_GTK 9522#ifdef USE_GTK
8759 if (FRAME_GTK_WIDGET (f)) 9523 if (FRAME_GTK_WIDGET (f))
@@ -8767,9 +9531,7 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
8767#else /* not USE_GTK */ 9531#else /* not USE_GTK */
8768 9532
8769 x_set_window_size_1 (f, change_gravity, width, height, pixelwise); 9533 x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
8770#if !defined USE_X_TOOLKIT
8771 x_clear_under_internal_border (f); 9534 x_clear_under_internal_border (f);
8772#endif
8773 9535
8774#endif /* not USE_GTK */ 9536#endif /* not USE_GTK */
8775 9537
@@ -8783,6 +9545,8 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
8783 cancel_mouse_face (f); 9545 cancel_mouse_face (f);
8784 9546
8785 unblock_input (); 9547 unblock_input ();
9548
9549 do_pending_window_change (0);
8786} 9550}
8787 9551
8788/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ 9552/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
@@ -9419,6 +10183,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
9419 XSizeHints size_hints; 10183 XSizeHints size_hints;
9420 Window window = FRAME_OUTER_WINDOW (f); 10184 Window window = FRAME_OUTER_WINDOW (f);
9421 10185
10186 if (!window)
10187 return;
10188
9422#ifdef USE_X_TOOLKIT 10189#ifdef USE_X_TOOLKIT
9423 if (f->output_data.x->widget) 10190 if (f->output_data.x->widget)
9424 { 10191 {
@@ -9452,8 +10219,6 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
9452 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); 10219 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9453 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); 10220 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9454 10221
9455 check_frame_size (f, &min_cols, &min_rows, 0);
9456
9457 if (frame_resize_pixelwise) 10222 if (frame_resize_pixelwise)
9458 /* Needed to prevent a bad protocol error crash when making the 10223 /* Needed to prevent a bad protocol error crash when making the
9459 frame size very small. */ 10224 frame size very small. */
@@ -10079,6 +10844,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10079 dpyinfo->vertical_scroll_bar_cursor 10844 dpyinfo->vertical_scroll_bar_cursor
10080 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow); 10845 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10081 10846
10847 dpyinfo->horizontal_scroll_bar_cursor
10848 = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow);
10849
10082 xrdb = x_load_resources (dpyinfo->display, xrm_option, 10850 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10083 resource_name, EMACS_CLASS); 10851 resource_name, EMACS_CLASS);
10084#ifdef HAVE_XRMSETDATABASE 10852#ifdef HAVE_XRMSETDATABASE
@@ -10214,6 +10982,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10214 ATOM_REFS_INIT ("DONE", Xatom_DONE) 10982 ATOM_REFS_INIT ("DONE", Xatom_DONE)
10215 ATOM_REFS_INIT ("PAGE", Xatom_PAGE) 10983 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
10216 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) 10984 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
10985 ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
10217 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) 10986 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
10218 /* EWMH */ 10987 /* EWMH */
10219 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) 10988 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
@@ -10602,6 +11371,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
10602 terminal->popup_dialog_hook = xw_popup_dialog; 11371 terminal->popup_dialog_hook = xw_popup_dialog;
10603#endif 11372#endif
10604 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; 11373 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
11374 terminal->set_horizontal_scroll_bar_hook = XTset_horizontal_scroll_bar;
10605 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars; 11375 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10606 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar; 11376 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10607 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars; 11377 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;