/* Implementation of GUI terminal on the Microsoft Windows API.
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "process.h"
#include "atimer.h"
#include "keymap.h"
+#include "menu.h"
#ifdef WINDOWSNT
#include "w32.h" /* for filename_from_utf16, filename_from_ansi */
HANDLE hMainThread = NULL;
int vertical_scroll_bar_min_handle;
+int horizontal_scroll_bar_min_handle;
int vertical_scroll_bar_top_border;
int vertical_scroll_bar_bottom_border;
+int horizontal_scroll_bar_left_border;
+int horizontal_scroll_bar_right_border;
int last_scroll_bar_drag_pos;
if (!pfnSetLayeredWindowAttributes)
return;
- if (dpyinfo->x_highlight_frame == f)
+ if (dpyinfo->w32_focus_frame == f)
alpha = f->alpha[0];
else
alpha = f->alpha[1];
w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
- RECT r;
- HDC hdc;
- struct face *face;
-
- r.left = x0;
- r.right = x1;
- r.top = y0;
- r.bottom = y1;
-
- hdc = get_frame_dc (f);
- face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
- if (face)
- w32_fill_rect (f, hdc, face->foreground, &r);
+ HDC hdc = get_frame_dc (f);
+ struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+ struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+ struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+ unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+ unsigned long color_first = (face_first
+ ? face_first->foreground
+ : FRAME_FOREGROUND_PIXEL (f));
+ unsigned long color_last = (face_last
+ ? face_last->foreground
+ : FRAME_FOREGROUND_PIXEL (f));
+
+ if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+ /* Vertical. */
+ {
+ w32_fill_area_abs (f, hdc, color_first, x0, y0, x0 + 1, y1);
+ w32_fill_area_abs (f, hdc, color, x0 + 1, y0, x1 - 1, y1);
+ w32_fill_area_abs (f, hdc, color_last, x1 - 1, y0, x1, y1);
+ }
+ else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+ /* Horizontal. */
+ {
+ w32_fill_area_abs (f, hdc, color_first, x0, y0, x1, y0 + 1);
+ w32_fill_area_abs (f, hdc, color, x0, y0 + 1, x1, y1 - 1);
+ w32_fill_area_abs (f, hdc, color_last, x0, y1 - 1, x1, y1);
+ }
else
- w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+ w32_fill_area_abs (f, hdc, color, x0, y0, x1, y1);
release_frame_dc (f, hdc);
}
-
/* End update of window W.
Draw vertical borders between horizontally adjacent windows, and
hdc = get_frame_dc (f);
- if (!p->overlay_p)
- {
- int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (bx < 0)
- {
- /* Bitmap fills the fringe. */
- if (bar_area_x + bar_area_width == p->x)
- bx = bar_area_x + sb_width;
- else if (p->x + p->wd == bar_area_x)
- bx = bar_area_x;
- if (bx >= 0)
- {
- int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
- nx = bar_area_width - sb_width;
- by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y));
- ny = row->visible_height;
- }
- }
- else
- {
- if (bar_area_x + bar_area_width == bx)
- {
- bx = bar_area_x + sb_width;
- nx += bar_area_width - sb_width;
- }
- else if (bx + nx == bar_area_x)
- nx += bar_area_width - sb_width;
- }
- }
- }
-
- if (bx >= 0 && nx > 0)
- w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
- }
-
/* Must clip because of partially visible lines. */
w32_clip_to_row (w, row, ANY_AREA, hdc);
+ if (p->bx >= 0 && !p->overlay_p)
+ w32_fill_area (f, hdc, face->background,
+ p->bx, p->by, p->nx, p->ny);
+
if (p->which && p->which < max_fringe_bmp)
{
HBITMAP pixmap = fringe_bmp[p->which];
else
face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
s->face = FACE_FROM_ID (s->f, face_id);
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+ prepare_face_for_display (s->f, s->face);
/* If font in this face is same as S->font, use it. */
if (s->font == s->face->font)
static inline void
x_set_glyph_string_gc (struct glyph_string *s)
{
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+ prepare_face_for_display (s->f, s->face);
if (s->hl == DRAW_NORMAL_TEXT)
{
s->stippled_p = s->face->stipple != 0;
}
else
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
+ emacs_abort ();
/* GC must have been set. */
eassert (s->gc != 0);
x_draw_image_relief (struct glyph_string *s)
{
int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
+ int extra_x, extra_y;
RECT r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
x1 = x + s->slice.width - 1;
y1 = y + s->slice.height - 1;
+
+ extra_x = extra_y = 0;
+ if (s->face->id == TOOL_BAR_FACE_ID)
+ {
+ if (CONSP (Vtool_bar_button_margin)
+ && INTEGERP (XCAR (Vtool_bar_button_margin))
+ && INTEGERP (XCDR (Vtool_bar_button_margin)))
+ {
+ extra_x = XINT (XCAR (Vtool_bar_button_margin));
+ extra_y = XINT (XCDR (Vtool_bar_button_margin));
+ }
+ else if (INTEGERP (Vtool_bar_button_margin))
+ extra_x = extra_y = XINT (Vtool_bar_button_margin);
+ }
+
top_p = bot_p = left_p = right_p = 0;
if (s->slice.x == 0)
- x -= thick, left_p = 1;
+ x -= thick + extra_x, left_p = 1;
if (s->slice.y == 0)
- y -= thick, top_p = 1;
+ y -= thick + extra_y, top_p = 1;
if (s->slice.x + s->slice.width == s->img->width)
- x1 += thick, right_p = 1;
+ x1 += thick + extra_x, right_p = 1;
if (s->slice.y + s->slice.height == s->img->height)
- y1 += thick, bot_p = 1;
+ y1 += thick + extra_y, bot_p = 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
int x, y;
int box_line_hwidth = eabs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
- int height;
+ int height, width;
HBITMAP pixmap = 0;
- height = s->height - 2 * box_line_vwidth;
+ height = s->height;
+ if (s->slice.y == 0)
+ height -= box_line_vwidth;
+ if (s->slice.y + s->slice.height >= s->img->height)
+ height -= box_line_vwidth;
/* Fill background with face under the image. Do it only if row is
taller than image or if image has a clip mask to reduce
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
+ width = s->background_width;
x = s->x;
if (s->first_glyph->left_box_line_p
&& s->slice.x == 0)
- x += box_line_hwidth;
+ {
+ x += box_line_hwidth;
+ width -= box_line_hwidth;
+ }
y = s->y;
if (s->slice.y == 0)
}
else
#endif
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+ x_draw_glyph_string_bg_rect (s, x, y, width, height);
s->background_filled_p = 1;
}
fringes of W. */
window_box (w, ANY_AREA, &x, &y, &width, &height);
- /* If the fringe is adjacent to the left (right) scroll bar of a
- leftmost (rightmost, respectively) window, then extend its
- background to the gap between the fringe and the bar. */
- if ((WINDOW_LEFTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
- || (WINDOW_RIGHTMOST_P (w)
- && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
- {
- int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (sb_width > 0)
- {
- int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
- if (bar_area_x + bar_area_width == x)
- {
- x = bar_area_x + sb_width;
- width += bar_area_width - sb_width;
- }
- else if (x + width == bar_area_x)
- width += bar_area_width - sb_width;
- }
- }
-
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
bottom_y = y + height;
char name_a[MAX_PATH];
char file[MAX_UTF8_PATH];
#endif
- int i, len;
+ int i;
result->kind = DRAG_N_DROP_EVENT;
result->code = 0;
Mouse Face
************************************************************************/
-static struct scroll_bar *x_window_to_scroll_bar (Window);
+static struct scroll_bar *x_window_to_scroll_bar (Window, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
unsigned long *);
+static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
+ enum scroll_bar_part *,
+ Lisp_Object *, Lisp_Object *,
+ unsigned long *);
static void x_check_fullscreen (struct frame *);
static void
{
PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
}
+
/* Return the current position of the mouse.
*fp should be a frame which indicates which display to ask about.
block_input ();
if (dpyinfo->last_mouse_scroll_bar && insist == 0)
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ {
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+
+ if (bar->horizontal)
+ x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ else
+ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ }
else
{
POINT pt;
if (! f1)
{
struct scroll_bar *bar
- = x_window_to_scroll_bar (WindowFromPoint (pt));
+ = x_window_to_scroll_bar (WindowFromPoint (pt), 2);
if (bar)
- {
- f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
- }
+ f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
}
if (f1 == 0 && insist > 0)
/* Scroll bar support. */
-/* Given a window ID, find the struct scroll_bar which manages it.
- This can be called in GC, so we have to make sure to strip off mark
- bits. */
+/* Given a window ID, find the struct scroll_bar which manages it
+ vertically. This can be called in GC, so we have to make sure to
+ strip off mark bits. */
static struct scroll_bar *
-x_window_to_scroll_bar (Window window_id)
+x_window_to_scroll_bar (Window window_id, int type)
{
Lisp_Object tail, frame;
condemned = Qnil,
! NILP (bar));
bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
+ if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id
+ && (type = 2
+ || (type == 1 && XSCROLL_BAR (bar)->horizontal)
+ || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
return XSCROLL_BAR (bar);
}
\f
-/* Set the thumb size and position of scroll bar BAR. We are currently
+/* Set the thumb size and position of vertical scroll bar BAR. We are currently
displaying PORTION out of a whole WHOLE, and our position POSITION. */
static void
/* We use the whole scroll-bar height in the calculations below, to
avoid strange effects like scrolling backwards when just clicking
on the handle (without moving it). */
- double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
+ double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height)
+ VERTICAL_SCROLL_BAR_MIN_HANDLE;
int sb_page, sb_pos;
- BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+ BOOL draggingp = bar->dragging ? TRUE : FALSE;
SCROLLINFO si;
/* We used to change the nPage setting while dragging the handle,
unblock_input ();
}
+/* Set the thumb size and position of horizontal scroll bar BAR. We are currently
+ displaying PORTION out of a whole WHOLE, and our position POSITION. */
+
+static void
+w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
+ int portion, int position, int whole)
+{
+ Window w = SCROLL_BAR_W32_WINDOW (bar);
+ SCROLLINFO si;
+
+ block_input ();
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = whole;
+ /* Allow nPage to be one larger than nPos so we don't allow to scroll
+ an already fully visible buffer. */
+ si.nPage = min (portion, si.nMax) + 1;
+ si.nPos = min (position, si.nMax);
+ SetScrollInfo (w, SB_CTL, &si, TRUE);
+
+ unblock_input ();
+}
+
\f
/************************************************************************
Scroll bars, general
************************************************************************/
static HWND
-my_create_scrollbar (struct frame * f, struct scroll_bar * bar)
+my_create_vscrollbar (struct frame * f, struct scroll_bar * bar)
{
return (HWND) SendMessage (FRAME_W32_WINDOW (f),
- WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
+ WM_EMACS_CREATEVSCROLLBAR, (WPARAM) f,
+ (LPARAM) bar);
+}
+
+static HWND
+my_create_hscrollbar (struct frame * f, struct scroll_bar * bar)
+{
+ return (HWND) SendMessage (FRAME_W32_WINDOW (f),
+ WM_EMACS_CREATEHSCROLLBAR, (WPARAM) f,
(LPARAM) bar);
}
scroll bar. */
static struct scroll_bar *
-x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
+x_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HWND hwnd;
SCROLLINFO si;
struct scroll_bar *bar
- = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, fringe_extended_p, PVEC_OTHER);
+ = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, top, PVEC_OTHER);
Lisp_Object barobj;
block_input ();
XSETWINDOW (bar->window, w);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
- bar->dragging = Qnil;
- bar->fringe_extended_p = 0;
+ bar->top = top;
+ bar->left = left;
+ bar->width = width;
+ bar->height = height;
+ bar->start = 0;
+ bar->end = 0;
+ bar->dragging = 0;
+ bar->horizontal = horizontal;
/* Requires geometry to be set before call to create the real window */
- hwnd = my_create_scrollbar (f, bar);
+ if (horizontal)
+ hwnd = my_create_hscrollbar (f, bar);
+ else
+ hwnd = my_create_vscrollbar (f, bar);
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0;
- si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
- + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+ if (horizontal)
+ si.nMax = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width)
+ + HORIZONTAL_SCROLL_BAR_MIN_HANDLE;
+ else
+ si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ + VERTICAL_SCROLL_BAR_MIN_HANDLE;
si.nPage = si.nMax;
si.nPos = 0;
my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
/* Dissociate this scroll bar from its window. */
- wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
+ if (bar->horizontal)
+ wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
+ else
+ wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
unblock_input ();
}
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
+/* Set the handle of the vertical scroll bar for WINDOW to indicate that
+ we are displaying PORTION characters out of a total of WHOLE
+ characters, starting at POSITION. If WINDOW has no vertical scroll
+ bar, create one. */
static void
w32_set_vertical_scroll_bar (struct window *w,
int portion, int whole, int position)
struct frame *f = XFRAME (w->frame);
Lisp_Object barobj;
struct scroll_bar *bar;
- int top, height, left, sb_left, width, sb_width;
+ int top, height, left, width;
int window_y, window_height;
- bool fringe_extended_p;
/* Get window dimensions. */
window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
top = window_y;
- width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
height = window_height;
- /* Compute the left edge of the scroll bar area. */
+ /* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
-
- /* Compute the width of the scroll bar which might be less than
- the width of the area reserved for the scroll bar. */
- if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
- sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
- else
- sb_width = width;
-
- /* Compute the left edge of the scroll bar. */
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
- else
- sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-
- fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
+ width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
if (width > 0 && height > 0)
{
hdc = get_frame_dc (f);
- if (fringe_extended_p)
- w32_clear_area (f, hdc, sb_left, top, sb_width, height);
- else
- w32_clear_area (f, hdc, left, top, width, height);
+ w32_clear_area (f, hdc, left, top, width, height);
release_frame_dc (f, hdc);
}
unblock_input ();
- bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+ bar = x_scroll_bar_create (w, left, top, width, height, 0);
}
else
{
hwnd = SCROLL_BAR_W32_WINDOW (bar);
/* If already correctly positioned, do nothing. */
- if (XINT (bar->left) == sb_left
- && XINT (bar->top) == top
- && XINT (bar->width) == sb_width
- && XINT (bar->height) == height
- && bar->fringe_extended_p == fringe_extended_p)
+ if (bar->left == left
+ && bar->top == top
+ && bar->width == width
+ && bar->height == height)
{
/* Redraw after clear_frame. */
if (!my_show_window (f, hwnd, SW_NORMAL))
hdc = get_frame_dc (f);
/* Since Windows scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
- if (fringe_extended_p)
- w32_clear_area (f, hdc, sb_left, top, sb_width, height);
- else
- w32_clear_area (f, hdc, left, top, width, height);
+ w32_clear_area (f, hdc, left, top, width, height);
release_frame_dc (f, hdc);
}
/* Make sure scroll bar is "visible" before moving, to ensure the
area of the parent window now exposed will be refreshed. */
my_show_window (f, hwnd, SW_HIDE);
- MoveWindow (hwnd, sb_left, top, sb_width,
- max (height, 1), TRUE);
+ MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
si.cbSize = sizeof (si);
si.fMask = SIF_RANGE;
/* InvalidateRect (w, NULL, FALSE); */
/* Remember new settings. */
- XSETINT (bar->left, sb_left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, sb_width);
- XSETINT (bar->height, height);
+ bar->left = left;
+ bar->top = top;
+ bar->width = width;
+ bar->height = height;
unblock_input ();
}
}
- bar->fringe_extended_p = fringe_extended_p;
-
w32_set_scroll_bar_thumb (bar, portion, position, whole);
XSETVECTOR (barobj, bar);
wset_vertical_scroll_bar (w, barobj);
}
+/* Set the handle of the horizontal scroll bar for WINDOW to indicate
+ that we are displaying PORTION characters out of a total of WHOLE
+ characters, starting at POSITION. If WINDOW has no horizontal scroll
+ bar, create one. */
+static void
+w32_set_horizontal_scroll_bar (struct window *w,
+ int portion, int whole, int position)
+{
+ struct frame *f = XFRAME (w->frame);
+ Lisp_Object barobj;
+ struct scroll_bar *bar;
+ int top, height, left, width;
+ int window_x, window_width;
+ int clear_left = WINDOW_LEFT_EDGE_X (w);
+ int clear_width = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+
+ /* Get window dimensions. */
+ window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
+ left = window_x;
+ height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+ width = window_width;
+ top = WINDOW_SCROLL_BAR_AREA_Y (w);
+
+ /* Does the scroll bar exist yet? */
+ if (NILP (w->horizontal_scroll_bar))
+ {
+ HDC hdc;
+ block_input ();
+ if (width > 0 && height > 0)
+ {
+ hdc = get_frame_dc (f);
+ w32_clear_area (f, hdc, clear_left, top, clear_width, height);
+ release_frame_dc (f, hdc);
+ }
+ unblock_input ();
+
+ bar = x_scroll_bar_create (w, left, top, width, height, 1);
+ }
+ else
+ {
+ /* It may just need to be moved and resized. */
+ HWND hwnd;
+
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+ hwnd = SCROLL_BAR_W32_WINDOW (bar);
+
+ /* If already correctly positioned, do nothing. */
+ if (bar->left == left && bar->top == top
+ && bar->width == width && bar->height == height)
+ {
+ /* Redraw after clear_frame. */
+ if (!my_show_window (f, hwnd, SW_NORMAL))
+ InvalidateRect (hwnd, NULL, FALSE);
+ }
+ else
+ {
+ HDC hdc;
+ SCROLLINFO si;
+
+ block_input ();
+ if (width && height)
+ {
+ hdc = get_frame_dc (f);
+ /* Since Windows scroll bars are smaller than the space reserved
+ for them on the frame, we have to clear "under" them. */
+ w32_clear_area (f, hdc, clear_left, top, clear_width, height);
+ release_frame_dc (f, hdc);
+ }
+ /* Make sure scroll bar is "visible" before moving, to ensure the
+ area of the parent window now exposed will be refreshed. */
+ my_show_window (f, hwnd, SW_HIDE);
+ MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
+
+ /* +++ SetScrollInfo +++ */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = whole;
+ si.nPage = min (portion, si.nMax) + 1;
+ si.nPos = min (position, si.nMax);
+ SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
+
+ my_show_window (f, hwnd, SW_NORMAL);
+ /* InvalidateRect (w, NULL, FALSE); */
+
+ /* Remember new settings. */
+ bar->left = left;
+ bar->top = top;
+ bar->width = width;
+ bar->height = height;
+
+ unblock_input ();
+ }
+ }
+
+ w32_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
+ XSETVECTOR (barobj, bar);
+ wset_horizontal_scroll_bar (w, barobj);
+}
+
/* The following three hooks are used when we're doing a thorough
redisplay of the frame. We don't explicitly know which scroll bars
static void
w32_condemn_scroll_bars (struct frame *frame)
{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
+ if (!NILP (FRAME_SCROLL_BARS (frame)))
{
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- fset_condemned_scroll_bars (frame, bar);
+ if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+ {
+ /* Prepend scrollbars to already condemned ones. */
+ Lisp_Object last = FRAME_SCROLL_BARS (frame);
+
+ while (!NILP (XSCROLL_BAR (last)->next))
+ last = XSCROLL_BAR (last)->next;
+
+ XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+ XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
+ }
+
+ fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
+ fset_scroll_bars (frame, Qnil);
}
}
Note that WINDOW isn't necessarily condemned at all. */
static void
-w32_redeem_scroll_bar (struct window *window)
+w32_redeem_scroll_bar (struct window *w)
{
struct scroll_bar *bar;
Lisp_Object barobj;
struct frame *f;
/* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
+ if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
emacs_abort ();
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- f = XFRAME (WINDOW_FRAME (window));
- if (NILP (bar->prev))
+ if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
{
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- fset_condemned_scroll_bars (f, bar->next);
+ bar = XSCROLL_BAR (w->vertical_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ goto horizontal;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->vertical_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- emacs_abort ();
+ XSCROLL_BAR (bar->prev)->next = bar->next;
+
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
+ horizontal:
+ if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+ {
+ bar = XSCROLL_BAR (w->horizontal_scroll_bar);
+ /* Unlink it from the condemned list. */
+ f = XFRAME (WINDOW_FRAME (w));
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ return;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ w->horizontal_scroll_bar))
+ fset_condemned_scroll_bars (f, bar->next);
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ emacs_abort ();
+ }
+ else
+ XSCROLL_BAR (bar->prev)->next = bar->next;
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (barobj, bar);
- fset_scroll_bars (f, barobj);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (barobj, bar);
+ fset_scroll_bars (f, barobj);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ }
}
/* Remove all scroll bars on FRAME that haven't been saved since the
and they should get garbage-collected. */
}
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than NO_EVENT, it is enqueued.
+/* Handle a mouse click on the vertical scroll bar BAR. If
+ *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
+ enqueued.
This may be called from a signal handler, so we have to ignore GC
mark bits. */
emacs_event->timestamp = msg->msg.time;
{
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
int y;
- int dragging = !NILP (bar->dragging);
+ int dragging = bar->dragging;
SCROLLINFO si;
+ int sb_event = LOWORD (msg->msg.wParam);
si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
+ if (sb_event == SB_THUMBTRACK)
+ si.fMask = SIF_TRACKPOS;
+ else
+ si.fMask = SIF_POS;
GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
- y = si.nPos;
+ if (sb_event == SB_THUMBTRACK)
+ y = si.nTrackPos;
+ else
+ y = si.nPos;
- bar->dragging = Qnil;
+ bar->dragging = 0;
FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
- switch (LOWORD (msg->msg.wParam))
+ switch (sb_event)
{
case SB_LINEDOWN:
emacs_event->part = scroll_bar_down_arrow;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
- if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
- y = HIWORD (msg->msg.wParam);
- bar->dragging = Qt;
+ bar->dragging = 1; /* ??????? */
emacs_event->part = scroll_bar_handle;
/* "Silently" update current position. */
if (dragging)
{
SCROLLINFO si;
- int start = XINT (bar->start);
- int end = XINT (bar->end);
+ int start = bar->start;
+ int end = bar->end;
si.cbSize = sizeof (si);
si.fMask = SIF_PAGE | SIF_POS;
}
}
-/* Return information to the user about the current position of the mouse
- on the scroll bar. */
+/* Handle a mouse click on the horizontal scroll bar BAR. If
+ *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
+ enqueued.
+ This may be called from a signal handler, so we have to ignore GC
+ mark bits. */
+
+static int
+w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
+ struct input_event *emacs_event)
+{
+ if (! WINDOWP (bar->window))
+ emacs_abort ();
+
+ emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
+ emacs_event->code = 0;
+ /* not really meaningful to distinguish left/right */
+ emacs_event->modifiers = msg->dwModifiers;
+ emacs_event->frame_or_window = bar->window;
+ emacs_event->arg = Qnil;
+ emacs_event->timestamp = msg->msg.time;
+
+ {
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ int x, y;
+ int dragging = bar->dragging;
+ SCROLLINFO si;
+ int sb_event = LOWORD (msg->msg.wParam);
+
+ si.cbSize = sizeof (si);
+ if (sb_event == SB_THUMBTRACK)
+ si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
+ else
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+
+ GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+ if (sb_event == SB_THUMBTRACK)
+ x = si.nTrackPos;
+ else
+ x = si.nPos;
+ y = si.nMax - si.nPage;
+
+ bar->dragging = 0;
+ FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
+
+ switch (sb_event)
+ {
+ case SB_LINELEFT:
+ emacs_event->part = scroll_bar_left_arrow;
+ break;
+ case SB_LINERIGHT:
+ emacs_event->part = scroll_bar_right_arrow;
+ break;
+ case SB_PAGELEFT:
+ emacs_event->part = scroll_bar_before_handle;
+ break;
+ case SB_PAGERIGHT:
+ emacs_event->part = scroll_bar_after_handle;
+ break;
+ case SB_LEFT:
+ emacs_event->part = scroll_bar_horizontal_handle;
+ x = 0;
+ break;
+ case SB_RIGHT:
+ emacs_event->part = scroll_bar_horizontal_handle;
+ x = left_range;
+ break;
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ bar->dragging = 1;
+ emacs_event->part = scroll_bar_horizontal_handle;
+
+ /* "Silently" update current position. */
+ {
+ SCROLLINFO si;
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ si.nPos = min (x, XWINDOW (bar->window)->hscroll_whole - 1);
+ /* Remember apparent position (we actually lag behind the real
+ position, so don't set that directly). */
+ last_scroll_bar_drag_pos = x;
+
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+ }
+ break;
+ case SB_ENDSCROLL:
+ /* If this is the end of a drag sequence, then reset the scroll
+ handle size to normal and do a final redraw. Otherwise do
+ nothing. */
+ if (dragging)
+ {
+ SCROLLINFO si;
+ int start = bar->start;
+ int end = bar->end;
+
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ si.nPos = min (last_scroll_bar_drag_pos,
+ XWINDOW (bar->window)->hscroll_whole - 1);
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
+ }
+ /* fall through */
+ default:
+ emacs_event->kind = NO_EVENT;
+ return FALSE;
+ }
+
+ XSETINT (emacs_event->x, x);
+ XSETINT (emacs_event->y, y);
+
+ return TRUE;
+ }
+}
+
+/* Return information to the user about the current position of the mouse
+ on the vertical scroll bar. */
static void
x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
enum scroll_bar_part *part,
Window w = SCROLL_BAR_W32_WINDOW (bar);
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int pos;
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
SCROLLINFO si;
+ int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos);
block_input ();
*bar_window = bar->window;
si.cbSize = sizeof (si);
- si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+ if (sb_event == SB_THUMBTRACK)
+ si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
+ else
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
GetScrollInfo (w, SB_CTL, &si);
- pos = si.nPos;
+ if (sb_event == SB_THUMBTRACK)
+ pos = si.nTrackPos;
+ else
+ pos = si.nPos;
top_range = si.nMax - si.nPage + 1;
- switch (LOWORD (dpyinfo->last_mouse_scroll_bar_pos))
- {
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- *part = scroll_bar_handle;
- if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
- pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos);
- break;
- case SB_LINEDOWN:
- *part = scroll_bar_handle;
- pos++;
- break;
- default:
- *part = scroll_bar_handle;
- break;
- }
+ *part = scroll_bar_handle;
+ if (sb_event == SB_LINEDOWN)
+ pos++;
XSETINT (*x, pos);
XSETINT (*y, top_range);
unblock_input ();
}
+/* Return information to the user about the current position of the mouse
+ on the horizontal scroll bar. */
+static void
+x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
+ enum scroll_bar_part *part,
+ Lisp_Object *x, Lisp_Object *y,
+ unsigned long *time)
+{
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
+ Window w = SCROLL_BAR_W32_WINDOW (bar);
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ int pos;
+ int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ SCROLLINFO si;
+ int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos);
+
+ block_input ();
+
+ *fp = f;
+ *bar_window = bar->window;
+
+ si.cbSize = sizeof (si);
+ if (sb_event == SB_THUMBTRACK)
+ si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
+ else
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+
+ GetScrollInfo (w, SB_CTL, &si);
+ if (sb_event == SB_THUMBTRACK)
+ pos = si.nTrackPos;
+ else
+ pos = si.nPos;
+ left_range = si.nMax - si.nPage + 1;
+
+ *part = scroll_bar_handle;
+ if (sb_event == SB_LINERIGHT)
+ pos++;
+
+
+ XSETINT (*y, pos);
+ XSETINT (*x, left_range);
+
+ f->mouse_moved = 0;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+
+ *time = dpyinfo->last_mouse_movement_time;
+
+ unblock_input ();
+}
+
/* The screen has been cleared so we may have changed foreground or
background colors, and the scroll bars may need to be redrawn.
/* We can have scroll bars even if this is 0,
if we just turned off scroll bar mode.
But in that case we should not clear them. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ || FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
{
}
}
-\f
+static void
+set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
+{
+ register Lisp_Object old_alist_elt;
+
+ old_alist_elt = Fassq (prop, f->param_alist);
+ if (EQ (old_alist_elt, Qnil))
+ fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
+ else
+ Fsetcdr (old_alist_elt, val);
+}
+
/* The main W32 event-reading loop - w32_read_socket. */
/* Record the last 100 characters stored
Emacs events should reflect only motion after
the ButtonPress. */
if (f != 0)
- f->mouse_moved = 0;
-
- if (!tool_bar_p)
- last_tool_bar_item = -1;
+ {
+ f->mouse_moved = 0;
+ if (!tool_bar_p)
+ f->last_tool_bar_item = -1;
+ }
}
break;
}
should reflect only motion after the
ButtonPress. */
f->mouse_moved = 0;
+ f->last_tool_bar_item = -1;
}
dpyinfo->last_mouse_frame = f;
- last_tool_bar_item = -1;
}
break;
construct_drag_n_drop (&inev, &msg, f);
break;
+ case WM_HSCROLL:
+ {
+ struct scroll_bar *bar =
+ x_window_to_scroll_bar ((HWND)msg.msg.lParam, 1);
+
+ if (bar)
+ w32_horizontal_scroll_bar_handle_click (bar, &msg, &inev);
+ break;
+ }
+
case WM_VSCROLL:
{
struct scroll_bar *bar =
- x_window_to_scroll_bar ((HWND)msg.msg.lParam);
+ x_window_to_scroll_bar ((HWND)msg.msg.lParam, 0);
if (bar)
w32_scroll_bar_handle_click (bar, &msg, &inev);
record_asynch_buffer_change ();
}
- if (get_frame_param (f, Qfullscreen) == Qnil)
+ if (EQ (get_frame_param (f, Qfullscreen), Qnil))
set_frame_param (f, Qfullscreen, Qmaximized);
- else if (get_frame_param (f, Qfullscreen) != Qmaximized)
+ else if (! EQ (get_frame_param (f, Qfullscreen), Qmaximized))
set_frame_param (f, Qmaximized, Qmaximized);
break;
{
bool iconified = FRAME_ICONIFIED_P (f);
+ /* The following was made unconditional in a
+ pathetic attempt to fix bug#16967 in revision
+ 116716 but, considered counterproductive was made
+ conditional again in revision 116727. martin */
if (iconified)
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_ICONIFIED (f, 0);
here since Windows sends a WM_MOVE message
BEFORE telling us the Window is minimized
when the Window is iconified, with 3000,3000
- as the co-ords. */
+ as the co-ords. */
x_real_positions (f, &f->left_pos, &f->top_pos);
inev.kind = DEICONIFY_EVENT;
record_asynch_buffer_change ();
}
- if (get_frame_param (f, Qfullscreen) == Qmaximized)
+ if (EQ (get_frame_param (f, Qfullscreen), Qmaximized))
set_frame_param (f, Qfullscreen, Qnil);
- else if (get_frame_param (f, Qmaximized) != Qnil)
+ else if (! EQ (get_frame_param (f, Qmaximized), Qnil))
set_frame_param (f, Qmaximized, Qnil);
break;
width = rect.right - rect.left;
text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width);
text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height);
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
- columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
+ /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */
+ /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */
/* TODO: Clip size to the screen dimensions. */
change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
- /* Do we want to set these here ???? */
-/** FRAME_PIXEL_WIDTH (f) = width; **/
-/** FRAME_TEXT_WIDTH (f) = text_width; **/
-/** FRAME_PIXEL_HEIGHT (f) = height; **/
f->win_gravity = NorthWestGravity;
}
}
if (f)
{
dpyinfo->n_cbits = msg.msg.wParam;
+ /* The new display could have a different resolution, in
+ which case we must reconsider what fullscreen
+ means. */
+ x_check_fullscreen (f);
DebPrint (("display change: %d %d\n",
(short) LOWORD (msg.msg.lParam),
(short) HIWORD (msg.msg.lParam)));
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
+ int unit;
if (fontset < 0)
fontset = fontset_from_font (font_object);
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
- FRAME_COLUMN_WIDTH (f) = font->average_width;
+ FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
FRAME_LINE_HEIGHT (f) = font->height;
- compute_fringe_widths (f, 1);
-
- /* Compute the scroll bar width in character columns. */
+ /* Compute number of scrollbar columns. */
+ unit = FRAME_COLUMN_WIDTH (f);
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
- {
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f)
- = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
- }
+ FRAME_CONFIG_SCROLL_BAR_COLS (f)
+ = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
else
{
- int wid = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f) =
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
}
/* Now make the frame display the given font. */
doing it because it's done in Fx_show_tip, and it leads to
problems because the tip frame has no widget. */
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
- x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
+ adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0);
}
/* X version sets font of input methods here also. */
unblock_input ();
}
+/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
+ wanted positions of the WM window (not Emacs window).
+ Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+ window (FRAME_X_WINDOW).
+ */
+
+static void
+x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
+{
+ int newwidth = FRAME_COLS (f);
+ int newheight = FRAME_LINES (f);
+ Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ *top_pos = f->top_pos;
+ *left_pos = f->left_pos;
+
+ if (f->want_fullscreen & FULLSCREEN_HEIGHT)
+ {
+ int ph;
+
+ ph = x_display_pixel_height (dpyinfo);
+ newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
+ ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
+ newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
+ *top_pos = 0;
+ }
+
+ if (f->want_fullscreen & FULLSCREEN_WIDTH)
+ {
+ int pw;
+
+ pw = x_display_pixel_width (dpyinfo);
+ newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
+ pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
+ newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
+ *left_pos = 0;
+ }
+
+ *width = newwidth;
+ *height = newheight;
+}
/* Check if we need to resize the frame due to a fullscreen request.
If so needed, resize the frame. */
HWND hwnd = FRAME_W32_WINDOW(f);
DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
RECT rect;
+ enum fullscreen_type prev_fsmode = FRAME_PREV_FSMODE (f);
block_input();
f->want_fullscreen &= ~FULLSCREEN_WAIT;
if (FRAME_PREV_FSMODE (f) == FULLSCREEN_BOTH)
{
SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
- SetWindowPos (hwnd, NULL, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
- SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
- }
+ SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
+ }
+ else if (FRAME_PREV_FSMODE (f) == FULLSCREEN_HEIGHT
+ || FRAME_PREV_FSMODE (f) == FULLSCREEN_WIDTH)
+ SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
- w32_fullscreen_rect (hwnd, f->want_fullscreen,
- FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
FRAME_PREV_FSMODE (f) = f->want_fullscreen;
- if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
- PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0);
+
+ if (f->want_fullscreen == FULLSCREEN_NONE)
+ ShowWindow (hwnd, SW_SHOWNORMAL);
+ else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
+ {
+ if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH
+ || prev_fsmode == FULLSCREEN_HEIGHT)
+ /* Make window normal since otherwise the subsequent
+ maximization might fail in some cases. */
+ ShowWindow (hwnd, SW_SHOWNORMAL);
+ ShowWindow (hwnd, SW_MAXIMIZE);
+ }
else if (f->want_fullscreen == FULLSCREEN_BOTH)
{
+ w32_fullscreen_rect (hwnd, f->want_fullscreen,
+ FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
}
else
{
+ ShowWindow (hwnd, SW_SHOWNORMAL);
+ w32_fullscreen_rect (hwnd, f->want_fullscreen,
+ FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, 0);
}
x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
int pixelwidth, pixelheight;
+ RECT rect;
block_input ();
- check_frame_size (f, &width, &height, pixelwise);
- f->scroll_bar_actual_width
- = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
-
- compute_fringe_widths (f, 0);
-
if (pixelwise)
{
pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
- {
- RECT rect;
+ f->want_fullscreen = FULLSCREEN_NONE;
+ w32fullscreen_hook (f);
- rect.left = rect.top = 0;
- rect.right = pixelwidth;
- rect.bottom = pixelheight;
+ rect.left = rect.top = 0;
+ rect.right = pixelwidth;
+ rect.bottom = pixelheight;
- AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
+ AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
+ FRAME_EXTERNAL_MENU_BAR (f));
- my_set_window_pos (FRAME_W32_WINDOW (f),
- NULL,
- 0, 0,
- rect.right - rect.left,
- rect.bottom - rect.top,
- SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
- }
+ my_set_window_pos (FRAME_W32_WINDOW (f),
+ NULL,
+ 0, 0,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
-#if 0
- /* The following mirrors what is done in xterm.c. It appears to be
- for informing lisp of the new size immediately, while the actual
- resize will happen asynchronously. But on Windows, the menu bar
- automatically wraps when the frame is too narrow to contain it,
- and that causes any calculations made here to come out wrong. The
- end is some nasty buggy behavior, including the potential loss
- of the minibuffer.
+ /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
+ new pixel sizes to the frame and its subwindows.
+
+ Jason Rumney earlier refused to call change_frame_size right here
+ with the following argument:
+
+ The following mirrors what is done in xterm.c. It appears to be for
+ informing lisp of the new size immediately, while the actual resize
+ will happen asynchronously. But on Windows, the menu bar
+ automatically wraps when the frame is too narrow to contain it, and
+ that causes any calculations made here to come out wrong. The end
+ is some nasty buggy behavior, including the potential loss of the
+ minibuffer.
Disabling this code is either not sufficient to fix the problems
completely, or it causes fresh problems, but at least it removes
the most problematic symptom of the minibuffer becoming unusable.
- -----------------------------------------------------------------
-
- Now, strictly speaking, we can't be sure that this is accurate,
- but the window manager will get around to dealing with the size
- change request eventually, and we'll hear how it went when the
- ConfigureNotify event gets here.
-
- We could just not bother storing any of this information here,
- and let the ConfigureNotify event set everything up, but that
- might be kind of confusing to the Lisp code, since size changes
- wouldn't be reported in the frame parameters until some random
- point in the future when the ConfigureNotify event arrives.
-
- We pass 1 for DELAY since we can't run Lisp code inside of
- a BLOCK_INPUT. */
- change_frame_size (f, width, height, 0, 1, 0, 0);
- FRAME_PIXEL_WIDTH (f) = pixelwidth;
- FRAME_PIXEL_HEIGHT (f) = pixelheight;
-
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
-
- /* If cursor was outside the new size, mark it as off. */
- mark_window_cursors_off (XWINDOW (f->root_window));
-
- /* Clear out any recollection of where the mouse highlighting was,
- since it might be in a place that's outside the new frame size.
- Actually checking whether it is outside is a pain in the neck,
- so don't try--just let the highlighting be done afresh with new size. */
- cancel_mouse_face (f);
-#endif
+ However, as the discussion about how to handle frame size
+ parameters on Windows (Bug#1348, Bug#16028) shows, that cure seems
+ worse than the disease. In particular, menu bar wrapping looks
+ like a non-issue - maybe so because Windows eventually gets back to
+ us with the correct client rectangle anyway. But we have to avoid
+ calling change_frame_size with a delta of less than one canoncial
+ character size when frame_resize_pixelwise is nil, as explained in
+ the comment above. */
- unblock_input ();
-}
-\f
-/* Mouse warping. */
-
-void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
+ if (w32_enable_frame_resize_hack)
-void
-x_set_mouse_position (struct frame *f, int x, int y)
-{
- int pix_x, pix_y;
+ {
+ change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
+ FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+ 0, 1, 0, 1);
+ SET_FRAME_GARBAGED (f);
- pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
- pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
+ /* If cursor was outside the new size, mark it as off. */
+ mark_window_cursors_off (XWINDOW (f->root_window));
- if (pix_x < 0) pix_x = 0;
- if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
+ /* Clear out any recollection of where the mouse highlighting was,
+ since it might be in a place that's outside the new frame size.
+ Actually checking whether it is outside is a pain in the neck,
+ so don't try--just let the highlighting be done afresh with new
+ size. */
+ cancel_mouse_face (f);
+ }
- if (pix_y < 0) pix_y = 0;
- if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
+ unblock_input ();
- x_set_mouse_pixel_position (f, pix_x, pix_y);
+ do_pending_window_change (0);
}
+\f
+/* Mouse warping. */
void
-x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
+frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
{
RECT rect;
POINT pt;
void
x_focus_frame (struct frame *f)
{
+#if 0
struct w32_display_info *dpyinfo = &one_w32_display_info;
+#endif
/* Give input focus to frame. */
block_input ();
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
face. */
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
+ free_frame_faces (f);
if (FRAME_W32_WINDOW (f))
my_destroy_window (f, FRAME_W32_WINDOW (f));
free_frame_menubar (f);
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
-
xfree (f->output_data.w32);
f->output_data.w32 = NULL;
SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
- SetWindowLong (window, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (window, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ SetWindowLong (window, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
leave_crit ();
}
#endif /* GLYPH_DEBUG */
+/* Show hourglass cursor on frame F. */
+
+static void
+w32_show_hourglass (struct frame *f)
+{
+ if (!menubar_in_use && !current_popup_menu)
+ {
+ struct w32_output *w32 = FRAME_X_OUTPUT (f);
+
+ w32->hourglass_p = 1;
+ SetCursor (w32->hourglass_cursor);
+ }
+}
+
+/* Hide hourglass cursor on frame F. */
+
+static void
+w32_hide_hourglass (struct frame *f)
+{
+ struct w32_output *w32 = FRAME_X_OUTPUT (f);
+
+ w32->hourglass_p = 0;
+ SetCursor (w32->current_cursor);
+}
+
+/* FIXME: old code did that, but I don't know why. Anyway,
+ this is used for non-GUI frames (see cancel_hourglass). */
+
+void
+w32_arrow_cursor (void)
+{
+ SetCursor (w32_load_cursor (IDC_ARROW));
+}
-\f
/***********************************************************************
Initialization
***********************************************************************/
dpyinfo->smallest_font_height = 1;
dpyinfo->smallest_char_width = 1;
dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
+ dpyinfo->horizontal_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
/* TODO: dpyinfo->gray */
reset_mouse_highlight (&dpyinfo->mouse_highlight);
w32_draw_window_cursor,
w32_draw_vertical_window_border,
w32_draw_window_divider,
- w32_shift_glyphs_for_insert
+ w32_shift_glyphs_for_insert,
+ w32_show_hourglass,
+ w32_hide_hourglass
};
static void x_delete_terminal (struct terminal *term);
{
struct terminal *terminal;
- terminal = create_terminal ();
+ terminal = create_terminal (output_w32, &w32_redisplay_interface);
- terminal->type = output_w32;
terminal->display_info.w32 = dpyinfo;
dpyinfo->terminal = terminal;
terminal->ins_del_lines_hook = x_ins_del_lines;
terminal->delete_glyphs_hook = x_delete_glyphs;
terminal->ring_bell_hook = w32_ring_bell;
- terminal->reset_terminal_modes_hook = NULL;
- terminal->set_terminal_modes_hook = NULL;
terminal->update_begin_hook = x_update_begin;
terminal->update_end_hook = x_update_end;
- terminal->set_terminal_window_hook = NULL;
terminal->read_socket_hook = w32_read_socket;
terminal->frame_up_to_date_hook = w32_frame_up_to_date;
terminal->mouse_position_hook = w32_mouse_position;
terminal->frame_rehighlight_hook = w32_frame_rehighlight;
terminal->frame_raise_lower_hook = w32_frame_raise_lower;
terminal->fullscreen_hook = w32fullscreen_hook;
+ terminal->menu_show_hook = w32_menu_show;
+ terminal->popup_dialog_hook = w32_popup_dialog;
terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
+ terminal->set_horizontal_scroll_bar_hook = w32_set_horizontal_scroll_bar;
terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
-
terminal->delete_frame_hook = x_destroy_window;
terminal->delete_terminal_hook = x_delete_terminal;
-
- terminal->rif = &w32_redisplay_interface;
+ /* Other hooks are NULL by default. */
/* We don't yet support separate terminals on W32, so don't try to share
keyboards between virtual terminals that are on the same physical
if (dpyinfo->palette)
DeleteObject (dpyinfo->palette);
}
- xfree (dpyinfo->w32_id_name);
-
w32_reset_fringes ();
}
w32_initialize (void)
{
HANDLE shell;
- HRESULT (WINAPI * set_user_model) (wchar_t * id);
+ HRESULT (WINAPI * set_user_model) (const wchar_t * id);
baud_rate = 19200;
&w32_use_visible_system_caret, 0))
w32_use_visible_system_caret = 0;
- last_tool_bar_item = -1;
any_help_event_p = 0;
/* Initialize input mode: interrupt_input off, no flow control, allow
Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
{
- DWORD input_locale_id = ((DWORD_PTR) GetKeyboardLayout (0) & 0xffffffff);
- w32_keyboard_codepage =
- codepage_for_locale ((LCID) (input_locale_id & 0xffff));
+ LCID input_locale_id = LOWORD (GetKeyboardLayout (0));
+ w32_keyboard_codepage = codepage_for_locale (input_locale_id);
}
/* Create the window thread - it will terminate itself when the app
#undef LOAD_PROC
- /* Ensure scrollbar handle is at least 5 pixels. */
+ /* Ensure scrollbar handles are at least 5 pixels. */
vertical_scroll_bar_min_handle = 5;
+ horizontal_scroll_bar_min_handle = 5;
/* For either kind of scroll bar, take account of the arrows; these
effectively form the border of the main scroll bar range. */
vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
= GetSystemMetrics (SM_CYVSCROLL);
+ horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
+ = GetSystemMetrics (SM_CYHSCROLL);
}
}
Windows 8. It is set to nil on Windows 9X. */);
w32_unicode_filenames = 0;
+ DEFVAR_BOOL ("w32-enable-frame-resize-hack",
+ w32_enable_frame_resize_hack,
+ doc: /* Non-nil means enable hack for frame resizing on Windows.
+A value of nil means to resize frames by sending a corresponding request
+to the Windows API and changing the pixel sizes of the frame and its
+windows after the latter calls back. If this is non-nil, Emacs changes
+the pixel sizes of the frame and its windows at the time it sends the
+resize request to the API. */);
+ w32_enable_frame_resize_hack = 1;
+
/* Tell Emacs about this window system. */
Fprovide (Qw32, Qnil);
}