X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/63e6f4c820bb677bc915445c99041a51aef6bdab..bf5ddded70c11edaf3514b25da27fc71cfb8e965:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index 397ade12f0..8da2ffe5b7 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1,14 +1,14 @@ /* NeXT/Open/GNUstep / MacOSX communication module. -*- coding: utf-8 -*- -Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2015 Free Software +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -72,9 +72,26 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) extern NSString *NSMenuDidBeginTrackingNotification; +/* ========================================================================== + + NSTRACE, Trace support. + + ========================================================================== */ + #if NSTRACE_ENABLED -int nstrace_num = 0; -int nstrace_depth = 0; + +/* The following use "volatile" since they can be accessed from + parallel threads. */ +volatile int nstrace_num = 0; +volatile int nstrace_depth = 0; + +/* When 0, no trace is emitted. This is used by NSTRACE_WHEN and + NSTRACE_UNLESS to silence functions called. + + TODO: This should really be a thread-local variable, to avoid that + a function with disabled trace thread silence trace output in + another. However, in practice this seldom is a problem. */ +volatile int nstrace_enabled_global = 1; /* Called when nstrace_enabled goes out of scope. */ void nstrace_leave(int * pointer_to_nstrace_enabled) @@ -86,38 +103,24 @@ void nstrace_leave(int * pointer_to_nstrace_enabled) } -void ns_print_fullscreen_type_name (char const * s, int fs_type) +/* Called when nstrace_saved_enabled_global goes out of scope. */ +void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global) { - // This is a support function for the NSTRACE system, don't add a - // NSTRACE () here. However, a local `nstrace_enabled' variable is - // needed by the NSTRACE_MSG macros. - int nstrace_enabled = 1; + nstrace_enabled_global = *pointer_to_saved_enabled_global; +} + +char const * nstrace_fullscreen_type_name (int fs_type) +{ switch (fs_type) { - case FULLSCREEN_NONE: - NSTRACE_MSG ("%s: FULLSCREEN_NONE", s); - break; - - case FULLSCREEN_WIDTH: - NSTRACE_MSG ("%s: FULLSCREEN_WIDTH", s); - break; - - case FULLSCREEN_HEIGHT: - NSTRACE_MSG ("%s: FULLSCREEN_HEIGHT", s); - break; - - case FULLSCREEN_BOTH: - NSTRACE_MSG ("%s: FULLSCREEN_BOTH", s); - break; - - case FULLSCREEN_MAXIMIZED: - NSTRACE_MSG ("%s: FULLSCREEN_MAXIMIZED", s); - break; - - default: - NSTRACE_MSG ("%s: %d", s, fs_type); - break; + case -1: return "-1"; + case FULLSCREEN_NONE: return "FULLSCREEN_NONE"; + case FULLSCREEN_WIDTH: return "FULLSCREEN_WIDTH"; + case FULLSCREEN_HEIGHT: return "FULLSCREEN_HEIGHT"; + case FULLSCREEN_BOTH: return "FULLSCREEN_BOTH"; + case FULLSCREEN_MAXIMIZED: return "FULLSCREEN_MAXIMIZED"; + default: return "FULLSCREEN_?????"; } } #endif @@ -581,25 +584,31 @@ ns_load_path (void) return NULL; } -static void -ns_timeout (int usecs) -/* -------------------------------------------------------------------------- - Blocking timer utility used by ns_ring_bell - -------------------------------------------------------------------------- */ + +void +ns_init_locale (void) +/* OS X doesn't set any environment variables for the locale when run + from the GUI. Get the locale from the OS and set LANG. */ { - struct timespec wakeup = timespec_add (current_timespec (), - make_timespec (0, usecs * 1000)); + NSLocale *locale = [NSLocale currentLocale]; - /* Keep waiting until past the time wakeup. */ - while (1) + NSTRACE ("ns_init_locale"); + + @try { - struct timespec timeout, now = current_timespec (); - if (timespec_cmp (wakeup, now) <= 0) - break; - timeout = timespec_sub (wakeup, now); + /* It seems OS X should probably use UTF-8 everywhere. + 'localeIdentifier' does not specify the encoding, and I can't + find any way to get the OS to tell us which encoding to use, + so hard-code '.UTF-8'. */ + NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8", + [locale localeIdentifier]]; - /* Try to wait that long--but we might wake up sooner. */ - pselect (0, NULL, NULL, NULL, &timeout, NULL); + /* Set LANG to locale, but not if LANG is already set. */ + setenv("LANG", [localeID UTF8String], 0); + } + @catch (NSException *e) + { + NSLog (@"Locale detection failed: %@: %@", [e name], [e reason]); } } @@ -644,42 +653,130 @@ ns_release_autorelease_pool (void *pool) } -/* True, if the menu bar should be hidden. */ - static BOOL ns_menu_bar_should_be_hidden (void) +/* True, if the menu bar should be hidden. */ { return !NILP (ns_auto_hide_menu_bar) && [NSApp respondsToSelector:@selector(setPresentationOptions:)]; } -static CGFloat -ns_menu_bar_height (NSScreen *screen) -/* The height of the menu bar, if visible. */ +struct EmacsMargins +{ + CGFloat top; + CGFloat bottom; + CGFloat left; + CGFloat right; +}; + + +static struct EmacsMargins +ns_screen_margins (NSScreen *screen) +/* The parts of SCREEN used by the operating system. */ { - // NSTRACE ("ns_menu_bar_height"); + NSTRACE ("ns_screen_margins"); + + struct EmacsMargins margins; - CGFloat res; + NSRect screenFrame = [screen frame]; + NSRect screenVisibleFrame = [screen visibleFrame]; + /* Sometimes, visibleFrame isn't up-to-date with respect to a hidden + menu bar, check this explicitly. */ if (ns_menu_bar_should_be_hidden()) { - res = 0; + margins.top = 0; } else { - NSRect screenFrame = [screen frame]; - NSRect screenVisibleFrame = [screen visibleFrame]; - CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height; CGFloat visibleFrameTop = (screenVisibleFrame.origin.y + screenVisibleFrame.size.height); - res = frameTop - visibleFrameTop; + margins.top = frameTop - visibleFrameTop; + } + { + CGFloat frameRight = screenFrame.origin.x + screenFrame.size.width; + CGFloat visibleFrameRight = (screenVisibleFrame.origin.x + + screenVisibleFrame.size.width); + margins.right = frameRight - visibleFrameRight; + } + + margins.bottom = screenVisibleFrame.origin.y - screenFrame.origin.y; + margins.left = screenVisibleFrame.origin.x - screenFrame.origin.x; + + NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g", + margins.left, + margins.right, + margins.top, + margins.bottom); + + return margins; +} + + +/* A screen margin between 1 and DOCK_IGNORE_LIMIT (inclusive) is + assumed to contain a hidden dock. OS X currently use 4 pixels for + this, however, to be future compatible, a larger value is used. */ +#define DOCK_IGNORE_LIMIT 6 + +static struct EmacsMargins +ns_screen_margins_ignoring_hidden_dock (NSScreen *screen) +/* The parts of SCREEN used by the operating system, excluding the parts +reserved for an hidden dock. */ +{ + NSTRACE ("ns_screen_margins_ignoring_hidden_dock"); + + struct EmacsMargins margins = ns_screen_margins(screen); + + /* OS X (currently) reserved 4 pixels along the edge where a hidden + dock is located. Unfortunately, it's not possible to find the + location and information about if the dock is hidden. Instead, + it is assumed that if the margin of an edge is less than + DOCK_IGNORE_LIMIT, it contains a hidden dock. */ + if (margins.left <= DOCK_IGNORE_LIMIT) + { + margins.left = 0; + } + if (margins.right <= DOCK_IGNORE_LIMIT) + { + margins.right = 0; + } + if (margins.top <= DOCK_IGNORE_LIMIT) + { + margins.top = 0; + } + /* Note: This doesn't occur in current versions of OS X, but + included for completeness and future compatibility. */ + if (margins.bottom <= DOCK_IGNORE_LIMIT) + { + margins.bottom = 0; } - // NSTRACE_MSG (NSTRACE_FMT_RETURN "%.0f", res); + NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g", + margins.left, + margins.right, + margins.top, + margins.bottom); + + return margins; +} + + +static CGFloat +ns_menu_bar_height (NSScreen *screen) +/* The height of the menu bar, if visible. + + Note: Don't use this when fullscreen is enabled -- the screen + sometimes includes, sometimes excludes the menu bar area. */ +{ + struct EmacsMargins margins = ns_screen_margins(screen); + + CGFloat res = margins.top; + + NSTRACE ("ns_menu_bar_height " NSTRACE_FMT_RETURN " %.0f", res); return res; } @@ -733,7 +830,7 @@ ns_menu_bar_height (NSScreen *screen) // Result: Menu bar visible, frame placed immediately below the menu. // -static NSRect constrain_frame_rect(NSRect frameRect) +static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen) { NSTRACE ("constrain_frame_rect(" NSTRACE_FMT_RECT ")", NSTRACE_ARG_RECT (frameRect)); @@ -765,7 +862,11 @@ static NSRect constrain_frame_rect(NSRect frameRect) { multiscreenRect = NSUnionRect (multiscreenRect, scrRect); - menu_bar_height = max(menu_bar_height, ns_menu_bar_height (s)); + if (!isFullscreen) + { + CGFloat screen_menu_bar_height = ns_menu_bar_height (s); + menu_bar_height = max(menu_bar_height, screen_menu_bar_height); + } } } @@ -859,7 +960,7 @@ ns_constrain_all_frames (void) if (![view isFullscreen]) { [[view window] - setFrame:constrain_frame_rect([[view window] frame]) + setFrame:constrain_frame_rect([[view window] frame], false) display:NO]; } } @@ -919,7 +1020,7 @@ ns_update_begin (struct frame *f) -------------------------------------------------------------------------- */ { EmacsView *view = FRAME_NS_VIEW (f); - NSTRACE ("ns_update_begin"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin"); ns_update_auto_hide_menu_bar (); @@ -976,7 +1077,7 @@ ns_update_window_begin (struct window *w) struct frame *f = XFRAME (WINDOW_FRAME (w)); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - NSTRACE ("ns_update_window_begin"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_begin"); w->output_cursor = w->cursor; block_input (); @@ -1006,7 +1107,7 @@ ns_update_window_end (struct window *w, bool cursor_on_p, external (RIF) call; for one window called before update_end -------------------------------------------------------------------------- */ { - NSTRACE ("update_window_end"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_end"); /* note: this fn is nearly identical in all terms */ if (!w->pseudo_window_p) @@ -1045,7 +1146,7 @@ ns_update_end (struct frame *f) { EmacsView *view = FRAME_NS_VIEW (f); - NSTRACE ("ns_update_end"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end"); /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */ MOUSE_HL_INFO (f)->mouse_face_defer = 0; @@ -1070,11 +1171,11 @@ ns_focus (struct frame *f, NSRect *r, int n) the entire window. -------------------------------------------------------------------------- */ { -// NSTRACE ("ns_focus"); -/* static int c =0; - fprintf (stderr, "focus: %d", c++); - if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height); - fprintf (stderr, "\n"); */ + NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus"); + if (r != NULL) + { + NSTRACE_RECT ("r", *r); + } if (f != ns_updating_frame) { @@ -1114,7 +1215,7 @@ ns_unfocus (struct frame *f) Internal: Remove focus on given frame -------------------------------------------------------------------------- */ { -// NSTRACE ("ns_unfocus"); + NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus"); if (gsaved) { @@ -1158,6 +1259,135 @@ ns_clip_to_row (struct window *w, struct glyph_row *row, } +/* ========================================================================== + + Visible bell and beep. + + ========================================================================== */ + + +// This bell implementation shows the visual bell image asynchronously +// from the rest of Emacs. This is done by adding a NSView to the +// superview of the Emacs window and removing it using a timer. +// +// Unfortunately, some Emacs operations, like scrolling, is done using +// low-level primitives that copy the content of the window, including +// the bell image. To some extent, this is handled by removing the +// image prior to scrolling and marking that the window is in need for +// redisplay. +// +// To test this code, make sure that there is no artifacts of the bell +// image in the following situations. Use a non-empty buffer (like the +// tutorial) to ensure that a scroll is performed: +// +// * Single-window: C-g C-v +// +// * Side-by-windows: C-x 3 C-g C-v +// +// * Windows above each other: C-x 2 C-g C-v + +@interface EmacsBell : NSImageView +{ + // Number of currently active bell:s. + unsigned int nestCount; + NSView * mView; + bool isAttached; +} +- (void)show:(NSView *)view; +- (void)hide; +- (void)remove; +@end + +@implementation EmacsBell + +- (id)init; +{ + NSTRACE ("[EmacsBell init]"); + if ((self = [super init])) + { + nestCount = 0; + isAttached = false; +#ifdef NS_IMPL_GNUSTEP + // GNUstep doesn't provide named images. This was reported in + // 2011, see https://savannah.gnu.org/bugs/?33396 + // + // As a drop in replacement, a semitransparent gray square is used. + self.image = [[NSImage alloc] initWithSize:NSMakeSize(32 * 5, 32 * 5)]; + [self.image lockFocus]; + [[NSColor colorForEmacsRed:0.5 green:0.5 blue:0.5 alpha:0.5] set]; + NSRectFill(NSMakeRect(0, 0, 32, 32)); + [self.image unlockFocus]; +#else + self.image = [NSImage imageNamed:NSImageNameCaution]; + [self.image setSize:NSMakeSize(self.image.size.width * 5, + self.image.size.height * 5)]; +#endif + } + return self; +} + +- (void)show:(NSView *)view +{ + NSTRACE ("[EmacsBell show:]"); + NSTRACE_MSG ("nestCount: %u", nestCount); + + // Show the image, unless it's already shown. + if (nestCount == 0) + { + NSRect rect = [view bounds]; + NSPoint pos; + pos.x = rect.origin.x + (rect.size.width - self.image.size.width )/2; + pos.y = rect.origin.y + (rect.size.height - self.image.size.height)/2; + + [self setFrameOrigin:pos]; + [self setFrameSize:self.image.size]; + + isAttached = true; + mView = view; + [[[view window] contentView] addSubview:self + positioned:NSWindowAbove + relativeTo:nil]; + } + + ++nestCount; + + [self performSelector:@selector(hide) withObject:self afterDelay:0.5]; +} + + +- (void)hide +{ + // Note: Trace output from this method isn't shown, reason unknown. + // NSTRACE ("[EmacsBell hide]"); + + if (nestCount > 0) + --nestCount; + + // Remove the image once the last bell became inactive. + if (nestCount == 0) + { + [self remove]; + } +} + + +-(void)remove +{ + NSTRACE ("[EmacsBell remove]"); + if (isAttached) + { + NSTRACE_MSG ("removeFromSuperview"); + [self removeFromSuperview]; + mView.needsDisplay = YES; + isAttached = false; + } +} + +@end + + +static EmacsBell * bell_view = nil; + static void ns_ring_bell (struct frame *f) /* -------------------------------------------------------------------------- @@ -1167,37 +1397,23 @@ ns_ring_bell (struct frame *f) NSTRACE ("ns_ring_bell"); if (visible_bell) { - NSAutoreleasePool *pool; struct frame *frame = SELECTED_FRAME (); NSView *view; + if (bell_view == nil) + { + bell_view = [[EmacsBell alloc] init]; + [bell_view retain]; + } + block_input (); - pool = [[NSAutoreleasePool alloc] init]; view = FRAME_NS_VIEW (frame); if (view != nil) { - NSRect r, surr; - NSPoint dim = NSMakePoint (128, 128); - - r = [view bounds]; - r.origin.x += (r.size.width - dim.x) / 2; - r.origin.y += (r.size.height - dim.y) / 2; - r.size.width = dim.x; - r.size.height = dim.y; - surr = NSInsetRect (r, -2, -2); - ns_focus (frame, &surr, 1); - [[view window] cacheImageInRect: [view convertRect: surr toView:nil]]; - [ns_lookup_indexed_color (NS_FACE_FOREGROUND - (FRAME_DEFAULT_FACE (frame)), frame) set]; - NSRectFill (r); - [[view window] flushWindow]; - ns_timeout (150000); - [[view window] restoreCachedImage]; - [[view window] flushWindow]; - ns_unfocus (frame); + [bell_view show:view]; } - [pool release]; + unblock_input (); } else @@ -1206,6 +1422,21 @@ ns_ring_bell (struct frame *f) } } + +static void hide_bell () +/* -------------------------------------------------------------------------- + Ensure the bell is hidden. + -------------------------------------------------------------------------- */ +{ + NSTRACE ("hide_bell"); + + if (bell_view != nil) + { + [bell_view remove]; + } +} + + /* ========================================================================== Frame / window manager related functions @@ -1220,6 +1451,7 @@ ns_raise_frame (struct frame *f) -------------------------------------------------------------------------- */ { NSView *view; + check_window_system (f); view = FRAME_NS_VIEW (f); block_input (); @@ -1236,6 +1468,7 @@ ns_lower_frame (struct frame *f) -------------------------------------------------------------------------- */ { NSView *view; + check_window_system (f); view = FRAME_NS_VIEW (f); block_input (); @@ -1379,7 +1612,12 @@ x_iconify_frame (struct frame *f) [[view window] orderOut: NSApp]; [[view window] setFrame: t display: NO]; } + + /* Processing input while Emacs is being minimized can cause a + crash, so block it for the duration. */ + block_input(); [[view window] miniaturize: NSApp]; + unblock_input(); } /* Free X resources of frame F. */ @@ -1501,7 +1739,6 @@ x_set_window_size (struct frame *f, NSRect wr = [window frame]; int tb = FRAME_EXTERNAL_TOOL_BAR (f); int pixelwidth, pixelheight; - int rows, cols; int orig_height = wr.size.height; NSTRACE ("x_set_window_size"); @@ -1510,8 +1747,8 @@ x_set_window_size (struct frame *f, return; NSTRACE_RECT ("current", wr); - -/*fprintf (stderr, "\tsetWindowSize: %d x %d, pixelwise %d, font size %d x %d\n", width, height, pixelwise, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f));*/ + NSTRACE_MSG ("Width:%d Height:%d Pixelwise:%d", width, height, pixelwise); + NSTRACE_MSG ("Font %d x %d", FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); block_input (); @@ -1519,15 +1756,11 @@ x_set_window_size (struct frame *f, { pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); - cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); - rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight); } else { pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); - cols = width; - rows = height; } /* If we have a toolbar, take its height into account. */ @@ -1571,26 +1804,8 @@ x_set_window_size (struct frame *f, make_number (FRAME_NS_TITLEBAR_HEIGHT (f)), make_number (FRAME_TOOLBAR_HEIGHT (f)))); - NSTRACE_RECT ("setFrame", wr); [window setFrame: wr display: YES]; - /* This is a trick to compensate for Emacs' managing the scrollbar area - as a fixed number of standard character columns. Instead of leaving - blank space for the extra, we chopped it off above. Now for - left-hand scrollbars, we shift all rendering to the left by the - difference between the real width and Emacs' imagined one. For - right-hand bars, don't worry about it since the extra is never used. - (Obviously doesn't work for vertically split windows tho..) */ - { - NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) - ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) - - NS_SCROLL_BAR_WIDTH (f), 0) - : NSMakePoint (0, 0); - NSTRACE_RECT ("setFrame", wr); - [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)]; - [view setBoundsOrigin: origin]; - } - [view updateFrameSize: NO]; unblock_input (); } @@ -1728,7 +1943,8 @@ ns_get_color (const char *name, NSColor **col) float r = -1.0, g, b; NSString *nsname = [NSString stringWithUTF8String: name]; -/*fprintf (stderr, "ns_get_color: '%s'\n", name); */ + NSTRACE ("ns_get_color(%s, **)", name); + block_input (); if ([nsname isEqualToString: @"ns_selection_bg_color"]) @@ -1935,7 +2151,7 @@ ns_defined_color (struct frame *f, -------------------------------------------------------------------------- */ { NSColor *col; - NSTRACE ("ns_defined_color"); + NSTRACE_WHEN (NSTRACE_GROUP_COLOR, "ns_defined_color"); block_input (); if (ns_get_color (name, &col) != 0) /* Color not found */ @@ -1961,6 +2177,8 @@ x_set_frame_alpha (struct frame *f) double alpha = 1.0; double alpha_min = 1.0; + NSTRACE ("x_set_frame_alpha"); + if (dpyinfo->x_highlight_frame == f) alpha = f->alpha[0]; else @@ -2097,7 +2315,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, position = [view convertPoint: position fromView: nil]; remember_mouse_glyph (f, position.x, position.y, &dpyinfo->last_mouse_glyph); -/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */ + NSTRACE_POINT ("position", position); if (bar_window) *bar_window = Qnil; if (part) *part = scroll_bar_above_handle; @@ -2120,7 +2338,7 @@ ns_frame_up_to_date (struct frame *f) Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls. -------------------------------------------------------------------------- */ { - NSTRACE ("ns_frame_up_to_date"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_frame_up_to_date"); if (FRAME_NS_P (f)) { @@ -2231,7 +2449,7 @@ ns_clear_frame (struct frame *f) NSView *view = FRAME_NS_VIEW (f); NSRect r; - NSTRACE ("ns_clear_frame"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame"); /* comes on initial frame because we have after-make-frame-functions = select-frame */ @@ -2267,7 +2485,7 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) if (!view || !face) return; - NSTRACE ("ns_clear_frame_area"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area"); r = NSIntersectionRect (r, [view frame]); ns_focus (f, &r, 1); @@ -2282,8 +2500,12 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) static void ns_copy_bits (struct frame *f, NSRect src, NSRect dest) { + NSTRACE ("ns_copy_bits"); + if (FRAME_NS_VIEW (f)) { + hide_bell(); // Ensure the bell image isn't scrolled. + ns_focus (f, &dest, 1); [FRAME_NS_VIEW (f) scrollRect: src by: NSMakeSize (dest.origin.x - src.origin.x, @@ -2360,7 +2582,7 @@ ns_after_update_window_line (struct window *w, struct glyph_row *desired_row) struct frame *f; int width, height; - NSTRACE ("ns_after_update_window_line"); + NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_after_update_window_line"); /* begin copy from other terms */ eassert (w); @@ -2485,7 +2707,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, static EmacsImage **bimgs = NULL; static int nBimgs = 0; - NSTRACE ("ns_draw_fringe_bitmap"); + NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap"); NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh); @@ -2556,13 +2778,13 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, [img setXBMColor: bm_color]; } +#ifdef NS_IMPL_COCOA // Note: For periodic images, the full image height is "h + hd". // By using the height h, a suitable part of the image is used. NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h); NSTRACE_RECT ("fromRect", fromRect); -#ifdef NS_IMPL_COCOA [img drawInRect: r fromRect: fromRect operation: NSCompositeSourceOver @@ -2602,7 +2824,7 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, in mini-buffer windows when switching between echo area glyphs and mini-buffer. */ - NSTRACE ("dumpcursor"); + NSTRACE ("ns_draw_window_cursor"); if (!on_p) return; @@ -2639,7 +2861,10 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, { if (cursor_width < 1) cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); - w->phys_cursor_width = cursor_width; + + /* The bar cursor should never be wider than the glyph. */ + if (cursor_width < w->phys_cursor_width) + w->phys_cursor_width = cursor_width; } /* If we have an HBAR, "cursor_width" MAY specify height. */ else if (cursor_type == HBAR_CURSOR) @@ -2656,12 +2881,11 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, r.size.height = h; r.size.width = w->phys_cursor_width; - /* TODO: only needed in rare cases with last-resort font in HELLO.. - should we do this more efficiently? */ - ns_clip_to_row (w, glyph_row, ANY_AREA, NO); /* do ns_focus(f, &r, 1); if remove */ + /* Prevent the cursor from being drawn outside the text area. */ + ns_clip_to_row (w, glyph_row, TEXT_AREA, NO); /* do ns_focus(f, &r, 1); if remove */ - face = FACE_FROM_ID (f, phys_cursor_glyph->face_id); + face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id); if (face && NS_FACE_BACKGROUND (face) == ns_index_color (FRAME_CURSOR_COLOR (f), f)) { @@ -2733,11 +2957,12 @@ ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1) NSTRACE ("ns_draw_vertical_window_border"); - face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID); - if (face) - [ns_lookup_indexed_color(face->foreground, f) set]; + face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); ns_focus (f, &r, 1); + if (face) + [ns_lookup_indexed_color(face->foreground, f) set]; + NSRectFill(r); ns_unfocus (f); } @@ -2755,11 +2980,12 @@ ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) NSTRACE ("ns_draw_window_divider"); - face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID); - if (face) - [ns_lookup_indexed_color(face->foreground, f) set]; + face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID); ns_focus (f, &r, 1); + if (face) + [ns_lookup_indexed_color(face->foreground, f) set]; + NSRectFill(r); ns_unfocus (f); } @@ -3088,9 +3314,10 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s) if (s->hl == DRAW_MOUSE_FACE) { - face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); + face = FACE_FROM_ID_OR_NULL (s->f, + MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) - face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); + face = FACE_FROM_ID_OR_NULL (s->f, MOUSE_FACE_ID); } else face = s->face; @@ -3155,8 +3382,9 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) struct face *face; if (s->hl == DRAW_MOUSE_FACE) { - face = FACE_FROM_ID (s->f, - MOUSE_HL_INFO (s->f)->mouse_face_face_id); + face + = FACE_FROM_ID_OR_NULL (s->f, + MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } @@ -3222,7 +3450,8 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) with its background color), we must clear just the image area. */ if (s->hl == DRAW_MOUSE_FACE) { - face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); + face = FACE_FROM_ID_OR_NULL (s->f, + MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } @@ -3339,7 +3568,8 @@ ns_dumpglyphs_stretch (struct glyph_string *s) if (s->hl == DRAW_MOUSE_FACE) { - face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); + face = FACE_FROM_ID_OR_NULL (s->f, + MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); } @@ -3416,6 +3646,32 @@ ns_dumpglyphs_stretch (struct glyph_string *s) } +static void +ns_draw_glyph_string_foreground (struct glyph_string *s) +{ + int x, flags; + struct font *font = s->font; + + /* If first glyph of S has a left box line, start drawing the text + of S to the right of that box line. */ + if (s->face && s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p) + x = s->x + eabs (s->face->box_line_width); + else + x = s->x; + + flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR : + (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE : + (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND : + NS_DUMPGLYPH_NORMAL)); + + font->driver->draw + (s, s->cmp_from, s->nchars, x, s->ybase, + (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) + || flags == NS_DUMPGLYPH_MOUSEFACE); +} + + static void ns_draw_composite_glyph_string_foreground (struct glyph_string *s) { @@ -3514,12 +3770,12 @@ ns_draw_glyph_string (struct glyph_string *s) { /* TODO (optimize): focus for box and contents draw */ NSRect r[2]; - int n, flags; + int n; char box_drawn_p = 0; struct font *font = s->face->font; if (! font) font = FRAME_FONT (s->f); - NSTRACE ("ns_draw_glyph_string"); + NSTRACE_WHEN (NSTRACE_GROUP_GLYPHS, "ns_draw_glyph_string"); if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/) { @@ -3584,11 +3840,6 @@ ns_draw_glyph_string (struct glyph_string *s) ns_maybe_dumpglyphs_background (s, s->first_glyph->type == COMPOSITE_GLYPH); - flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR : - (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE : - (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND : - NS_DUMPGLYPH_NORMAL)); - if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR) { unsigned long tmp = NS_FACE_BACKGROUND (s->face); @@ -3602,10 +3853,7 @@ ns_draw_glyph_string (struct glyph_string *s) if (isComposite) ns_draw_composite_glyph_string_foreground (s); else - font->driver->draw - (s, s->cmp_from, s->nchars, s->x, s->ybase, - (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) - || flags == NS_DUMPGLYPH_MOUSEFACE); + ns_draw_glyph_string_foreground (s); } { @@ -3677,7 +3925,7 @@ ns_send_appdefined (int value) recognize and take as a command to halt the event loop. -------------------------------------------------------------------------- */ { - NSTRACE ("ns_send_appdefined"); + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_send_appdefined(%d)", value); #ifdef NS_IMPL_GNUSTEP // GNUstep needs postEvent to happen on the main thread. @@ -3851,7 +4099,10 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct input_event ev; int nevents; -/* NSTRACE ("ns_read_socket"); */ + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket"); + + if (apploopnr > 0) + return -1; /* Already within event loop. */ #ifdef HAVE_NATIVE_FS check_native_fs (); @@ -3935,7 +4186,10 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, struct input_event event; char c; -/* NSTRACE ("ns_select"); */ + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select"); + + if (apploopnr > 0) + return -1; /* Already within event loop. */ #ifdef HAVE_NATIVE_FS check_native_fs (); @@ -4117,7 +4371,7 @@ ns_set_vertical_scroll_bar (struct window *window, window_box (window, ANY_AREA, 0, &window_y, 0, &window_height); top = window_y; height = window_height; - width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f); + width = NS_SCROLL_BAR_WIDTH (f); left = WINDOW_SCROLL_BAR_AREA_X (window); r = NSMakeRect (left, top, width, height); @@ -4208,34 +4462,20 @@ ns_set_horizontal_scroll_bar (struct window *window, NSTRACE ("ns_set_horizontal_scroll_bar"); /* Get dimensions. */ - window_box (window, ANY_AREA, 0, &window_x, &window_width, 0); + window_box (window, ANY_AREA, &window_x, 0, &window_width, 0); left = window_x; width = window_width; - height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f); + height = NS_SCROLL_BAR_HEIGHT (f); top = WINDOW_SCROLL_BAR_AREA_Y (window); r = NSMakeRect (left, top, width, height); /* the parent view is flipped, so we need to flip y value */ v = [view frame]; - /* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */ r.origin.y = (v.size.height - r.size.height - r.origin.y); XSETWINDOW (win, window); block_input (); - if (WINDOW_TOTAL_COLS (window) < 5) - { - if (!NILP (window->horizontal_scroll_bar)) - { - bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); - [bar removeFromSuperview]; - wset_horizontal_scroll_bar (window, Qnil); - } - ns_clear_frame_area (f, left, top, width, height); - unblock_input (); - return; - } - if (NILP (window->horizontal_scroll_bar)) { if (width > 0 && height > 0) @@ -4250,16 +4490,22 @@ ns_set_horizontal_scroll_bar (struct window *window, NSRect oldRect; bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); oldRect = [bar frame]; - r.size.width = oldRect.size.width; if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r)) { - if (oldRect.origin.x != r.origin.x) - ns_clear_frame_area (f, left, top, width, height); + if (oldRect.origin.y != r.origin.y) + ns_clear_frame_area (f, left, top, width, height); [bar setFrame: r]; update_p = YES; } } + /* If there are both horizontal and vertical scroll-bars they leave + a square that belongs to neither. We need to clear it otherwise + it fills with junk. */ + if (!NILP (window->vertical_scroll_bar)) + ns_clear_frame_area (f, WINDOW_SCROLL_BAR_AREA_X (window), top, + NS_SCROLL_BAR_HEIGHT (f), height); + if (update_p) [bar setPosition: position portion: portion whole: whole]; unblock_input (); @@ -4297,13 +4543,15 @@ ns_redeem_scroll_bar (struct window *window) { id bar; NSTRACE ("ns_redeem_scroll_bar"); - if (!NILP (window->vertical_scroll_bar)) + if (!NILP (window->vertical_scroll_bar) + && WINDOW_HAS_VERTICAL_SCROLL_BAR (window)) { bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar reprieve]; } - if (!NILP (window->horizontal_scroll_bar)) + if (!NILP (window->horizontal_scroll_bar) + && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (window)) { bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); [bar reprieve]; @@ -4905,7 +5153,7 @@ ns_term_shutdown (int sig) - (void)stop: (id)sender { - NSTRACE ("[EmacsApp stop]"); + NSTRACE ("[EmacsApp stop:]"); shouldKeepRunning = NO; // Stop possible dialog also. Noop if no dialog present. @@ -4916,7 +5164,7 @@ ns_term_shutdown (int sig) - (void)logNotification: (NSNotification *)notification { - NSTRACE ("[EmacsApp logNotification]"); + NSTRACE ("[EmacsApp logNotification:]"); const char *name = [[notification name] UTF8String]; if (!strstr (name, "Update") && !strstr (name, "NSMenu") @@ -4934,8 +5182,8 @@ ns_term_shutdown (int sig) int type = [theEvent type]; NSWindow *window = [theEvent window]; - NSTRACE ("[EmacsApp sendEvent]"); -/*fprintf (stderr, "received event of type %d\t%d\n", type);*/ + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsApp sendEvent:]"); + NSTRACE_MSG ("Type: %d", type); #ifdef NS_IMPL_GNUSTEP // Keyboard events aren't propagated to file dialogs for some reason. @@ -5021,6 +5269,8 @@ ns_term_shutdown (int sig) } #endif + NSTRACE_UNSILENCE(); + [super sendEvent: theEvent]; } @@ -5041,7 +5291,7 @@ ns_term_shutdown (int sig) - (void)newFrame: (id)sender { - NSTRACE ("[EmacsApp newFrame]"); + NSTRACE ("[EmacsApp newFrame:]"); struct frame *emacsframe = SELECTED_FRAME (); NSEvent *theEvent = [NSApp currentEvent]; @@ -5058,7 +5308,7 @@ ns_term_shutdown (int sig) /* Open a file (used by below, after going into queue read by ns_read_socket) */ - (BOOL) openFile: (NSString *)fileName { - NSTRACE ("[EmacsApp openFile]"); + NSTRACE ("[EmacsApp openFile:]"); struct frame *emacsframe = SELECTED_FRAME (); NSEvent *theEvent = [NSApp currentEvent]; @@ -5088,7 +5338,7 @@ ns_term_shutdown (int sig) When application is loaded, terminate event loop in ns_term_init -------------------------------------------------------------------------- */ { - NSTRACE ("[EmacsApp applicationDidFinishLaunching]"); + NSTRACE ("[EmacsApp applicationDidFinishLaunching:]"); #ifdef NS_IMPL_GNUSTEP ((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES; @@ -5138,7 +5388,7 @@ ns_term_shutdown (int sig) - (void) terminate: (id)sender { - NSTRACE ("[EmacsApp terminate]"); + NSTRACE ("[EmacsApp terminate:]"); struct frame *emacsframe = SELECTED_FRAME (); @@ -5176,7 +5426,7 @@ runAlertPanel(NSString *title, - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender { - NSTRACE ("[EmacsApp applicationShouldTerminate]"); + NSTRACE ("[EmacsApp applicationShouldTerminate:]"); bool ret; @@ -5257,13 +5507,13 @@ not_in_argv (NSString *arg) /* TODO: these may help w/IO switching btwn terminal and NSApp */ - (void)applicationWillBecomeActive: (NSNotification *)notification { - NSTRACE ("[EmacsApp applicationWillBecomeActive]"); + NSTRACE ("[EmacsApp applicationWillBecomeActive:]"); //ns_app_active=YES; } - (void)applicationDidBecomeActive: (NSNotification *)notification { - NSTRACE ("[EmacsApp applicationDidBecomeActive]"); + NSTRACE ("[EmacsApp applicationDidBecomeActive:]"); #ifdef NS_IMPL_GNUSTEP if (! applicationDidFinishLaunchingCalled) @@ -5277,7 +5527,7 @@ not_in_argv (NSString *arg) } - (void)applicationDidResignActive: (NSNotification *)notification { - NSTRACE ("[EmacsApp applicationDidResignActive]"); + NSTRACE ("[EmacsApp applicationDidResignActive:]"); //ns_app_active=NO; ns_send_appdefined (-1); @@ -5422,6 +5672,8 @@ not_in_argv (NSString *arg) struct frame *emacsframe = SELECTED_FRAME (); NSEvent *theEvent = [NSApp currentEvent]; + NSTRACE ("[EmacsApp fulfillService:withArg:]"); + if (!emacs_event) return NO; @@ -5452,13 +5704,15 @@ not_in_argv (NSString *arg) /* needed to inform when window closed from LISP */ - (void) setWindowClosing: (BOOL)closing { + NSTRACE ("[EmacsView setWindowClosing:%d]", closing); + windowClosing = closing; } - (void)dealloc { - NSTRACE ("EmacsView_dealloc"); + NSTRACE ("[EmacsView dealloc]"); [toolbar release]; if (fs_state == FULLSCREEN_BOTH) [nonfs_window release]; @@ -5476,7 +5730,7 @@ not_in_argv (NSString *arg) CGFloat size; NSFont *nsfont; - NSTRACE ("changeFont"); + NSTRACE ("[EmacsView changeFont:]"); if (!emacs_event) return; @@ -5506,7 +5760,7 @@ not_in_argv (NSString *arg) - (BOOL)acceptsFirstResponder { - NSTRACE ("acceptsFirstResponder"); + NSTRACE ("[EmacsView acceptsFirstResponder]"); return YES; } @@ -5515,7 +5769,7 @@ not_in_argv (NSString *arg) { NSRect visible = [self visibleRect]; NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe); - NSTRACE ("resetCursorRects"); + NSTRACE ("[EmacsView resetCursorRects]"); if (currentCursor == nil) currentCursor = [NSCursor arrowCursor]; @@ -5540,7 +5794,7 @@ not_in_argv (NSString *arg) int left_is_none; unsigned int flags = [theEvent modifierFlags]; - NSTRACE ("keyDown"); + NSTRACE ("[EmacsView keyDown:]"); /* Rhapsody and OS X give up and down events for the arrow keys */ if (ns_fake_keydown == YES) @@ -5785,6 +6039,9 @@ not_in_argv (NSString *arg) { int flags = [theEvent modifierFlags]; int code = [theEvent keyCode]; + + NSTRACE ("[EmacsView keyUp:]"); + if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ && code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask)) { @@ -5809,6 +6066,8 @@ not_in_argv (NSString *arg) int len = [(NSString *)aString length]; int i; + NSTRACE ("[EmacsView insertText:]"); + if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len); processingCompose = NO; @@ -5842,6 +6101,9 @@ not_in_argv (NSString *arg) { NSString *str = [aString respondsToSelector: @selector (string)] ? [aString string] : aString; + + NSTRACE ("[EmacsView setMarkedText:selectedRange:]"); + if (NS_KEYLOG) NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str, (unsigned long)[str length], @@ -5869,6 +6131,8 @@ not_in_argv (NSString *arg) /* delete display of composing characters [not in ] */ - (void)deleteWorkingText { + NSTRACE ("[EmacsView deleteWorkingText]"); + if (workingText == nil) return; if (NS_KEYLOG) @@ -5888,12 +6152,16 @@ not_in_argv (NSString *arg) - (BOOL)hasMarkedText { + NSTRACE ("[EmacsView hasMarkedText]"); + return workingText != nil; } - (NSRange)markedRange { + NSTRACE ("[EmacsView markedRange]"); + NSRange rng = workingText != nil ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0); if (NS_KEYLOG) @@ -5904,6 +6172,8 @@ not_in_argv (NSString *arg) - (void)unmarkText { + NSTRACE ("[EmacsView unmarkText]"); + if (NS_KEYLOG) NSLog (@"unmark (accept) text"); [self deleteWorkingText]; @@ -5917,6 +6187,9 @@ not_in_argv (NSString *arg) NSRect rect; NSPoint pt; struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe)); + + NSTRACE ("[EmacsView firstRectForCharacterRange:]"); + if (NS_KEYLOG) NSLog (@"firstRectForCharRange request"); @@ -5927,8 +6200,14 @@ not_in_argv (NSString *arg) +FRAME_LINE_HEIGHT (emacsframe)); pt = [self convertPoint: pt toView: nil]; +#if !defined (NS_IMPL_COCOA) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 pt = [[self window] convertBaseToScreen: pt]; rect.origin = pt; +#else + rect.origin = pt; + rect = [[self window] convertRectToScreen: rect]; +#endif return rect; } @@ -5941,6 +6220,8 @@ not_in_argv (NSString *arg) - (void)doCommandBySelector: (SEL)aSelector { + NSTRACE ("[EmacsView doCommandBySelector:]"); + if (NS_KEYLOG) NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector)); @@ -6003,7 +6284,7 @@ not_in_argv (NSString *arg) struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - NSTRACE ("mouseDown"); + NSTRACE ("[EmacsView mouseDown:]"); [self deleteWorkingText]; @@ -6024,7 +6305,7 @@ not_in_argv (NSString *arg) delta = [theEvent deltaX]; if (delta == 0) { - NSTRACE ("deltaIsZero"); + NSTRACE_MSG ("deltaIsZero"); return; } emacs_event->kind = HORIZ_WHEEL_EVENT; @@ -6051,42 +6332,42 @@ not_in_argv (NSString *arg) - (void)rightMouseDown: (NSEvent *)theEvent { - NSTRACE ("rightMouseDown"); + NSTRACE ("[EmacsView rightMouseDown:]"); [self mouseDown: theEvent]; } - (void)otherMouseDown: (NSEvent *)theEvent { - NSTRACE ("otherMouseDown"); + NSTRACE ("[EmacsView otherMouseDown:]"); [self mouseDown: theEvent]; } - (void)mouseUp: (NSEvent *)theEvent { - NSTRACE ("mouseUp"); + NSTRACE ("[EmacsView mouseUp:]"); [self mouseDown: theEvent]; } - (void)rightMouseUp: (NSEvent *)theEvent { - NSTRACE ("rightMouseUp"); + NSTRACE ("[EmacsView rightMouseUp:]"); [self mouseDown: theEvent]; } - (void)otherMouseUp: (NSEvent *)theEvent { - NSTRACE ("otherMouseUp"); + NSTRACE ("[EmacsView otherMouseUp:]"); [self mouseDown: theEvent]; } - (void) scrollWheel: (NSEvent *)theEvent { - NSTRACE ("scrollWheel"); + NSTRACE ("[EmacsView scrollWheel:]"); [self mouseDown: theEvent]; } @@ -6099,7 +6380,7 @@ not_in_argv (NSString *arg) Lisp_Object frame; NSPoint pt; -// NSTRACE ("mouseMoved"); + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]"); dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e); pt = [self convertPoint: [e locationInWindow] fromView: nil]; @@ -6119,7 +6400,7 @@ not_in_argv (NSString *arg) if (!NILP (Vmouse_autoselect_window)) { - NSTRACE ("mouse_autoselect_window"); + NSTRACE_MSG ("mouse_autoselect_window"); static Lisp_Object last_mouse_window; Lisp_Object window = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0); @@ -6131,7 +6412,7 @@ not_in_argv (NSString *arg) || (EQ (XWINDOW (window)->frame, XWINDOW (selected_window)->frame)))) { - NSTRACE ("in_window"); + NSTRACE_MSG ("in_window"); emacs_event->kind = SELECT_WINDOW_EVENT; emacs_event->frame_or_window = window; EV_TRAILER2 (e); @@ -6161,21 +6442,21 @@ not_in_argv (NSString *arg) - (void)mouseDragged: (NSEvent *)e { - NSTRACE ("mouseDragged"); + NSTRACE ("[EmacsView mouseDragged:]"); [self mouseMoved: e]; } - (void)rightMouseDragged: (NSEvent *)e { - NSTRACE ("rightMouseDragged"); + NSTRACE ("[EmacsView rightMouseDragged:]"); [self mouseMoved: e]; } - (void)otherMouseDragged: (NSEvent *)e { - NSTRACE ("otherMouseDragged"); + NSTRACE ("[EmacsView otherMouseDragged:]"); [self mouseMoved: e]; } @@ -6184,7 +6465,7 @@ not_in_argv (NSString *arg) { NSEvent *e =[[self window] currentEvent]; - NSTRACE ("windowShouldClose"); + NSTRACE ("[EmacsView windowShouldClose:]"); windowClosing = YES; if (!emacs_event) return NO; @@ -6206,7 +6487,7 @@ not_in_argv (NSString *arg) int oldh = FRAME_PIXEL_HEIGHT (emacsframe); int neww, newh; - NSTRACE ("updateFrameSize"); + NSTRACE ("[EmacsView updateFrameSize:]"); NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh)); NSTRACE_RECT ("Original frame", wr); NSTRACE_MSG ("Original columns: %d", cols); @@ -6249,13 +6530,12 @@ not_in_argv (NSString *arg) if (rows < MINHEIGHT) rows = MINHEIGHT; - NSTRACE_MSG ("New columns: %d", cols); - NSTRACE_MSG ("New rows: %d", rows); + NSTRACE_MSG ("New columns: %d", cols); + NSTRACE_MSG ("New rows: %d", rows); if (oldr != rows || oldc != cols || neww != oldw || newh != oldh) { NSView *view = FRAME_NS_VIEW (emacsframe); - NSWindow *win = [view window]; change_frame_size (emacsframe, FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww), @@ -6265,8 +6545,9 @@ not_in_argv (NSString *arg) cancel_mouse_face (emacsframe); wr = NSMakeRect (0, 0, neww, newh); - NSTRACE_RECT ("setFrame", wr); + [view setFrame: wr]; + // to do: consider using [NSNotificationCenter postNotificationName:]. [self windowDidMove: // Update top/left. [NSNotification notificationWithName:NSWindowDidMoveNotification @@ -6283,7 +6564,7 @@ not_in_argv (NSString *arg) { int extra = 0; - NSTRACE ("windowWillResize: toSize: " NSTRACE_FMT_SIZE, + NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]", NSTRACE_ARG_SIZE (frameSize)); NSTRACE_RECT ("[sender frame]", [sender frame]); NSTRACE_FSTYPE ("fs_state", fs_state); @@ -6382,7 +6663,7 @@ not_in_argv (NSString *arg) - (void)windowDidResize: (NSNotification *)notification { - NSTRACE ("windowDidResize"); + NSTRACE ("[EmacsView windowDidResize:]"); if (!FRAME_LIVE_P (emacsframe)) { NSTRACE_MSG ("Ignored (frame dead)"); @@ -6425,6 +6706,8 @@ not_in_argv (NSString *arg) #ifdef NS_IMPL_COCOA - (void)viewDidEndLiveResize { + NSTRACE ("[EmacsView viewDidEndLiveResize]"); + [super viewDidEndLiveResize]; if (old_title != 0) { @@ -6449,7 +6732,7 @@ not_in_argv (NSString *arg) struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); struct frame *old_focus = dpyinfo->x_focus_frame; - NSTRACE ("windowDidBecomeKey"); + NSTRACE ("[EmacsView windowDidBecomeKey]"); if (emacsframe != old_focus) dpyinfo->x_focus_frame = emacsframe; @@ -6469,7 +6752,7 @@ not_in_argv (NSString *arg) { struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe; - NSTRACE ("windowDidResignKey"); + NSTRACE ("[EmacsView windowDidResignKey:]"); if (is_focus_frame) dpyinfo->x_focus_frame = 0; @@ -6504,7 +6787,16 @@ not_in_argv (NSString *arg) - (void)windowWillMiniaturize: sender { - NSTRACE ("windowWillMiniaturize"); + NSTRACE ("[EmacsView windowWillMiniaturize:]"); +} + + +- (void)setFrame:(NSRect)frameRect; +{ + NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]", + NSTRACE_ARG_RECT (frameRect)); + + [super setFrame:(NSRect)frameRect]; } @@ -6528,7 +6820,8 @@ not_in_argv (NSString *arg) NSColor *col; NSString *name; - NSTRACE ("initFrameFromEmacs"); + NSTRACE ("[EmacsView initFrameFromEmacs:]"); + NSTRACE_MSG ("cols:%d lines:%d", f->text_cols, f->text_lines); windowClosing = NO; processingCompose = NO; @@ -6543,8 +6836,6 @@ not_in_argv (NSString *arg) maximized_width = maximized_height = -1; nonfs_window = nil; -/*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */ - ns_userRect = NSMakeRect (0, 0, 0, 0); r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols), FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines)); @@ -6632,8 +6923,6 @@ not_in_argv (NSString *arg) IN_BOUND (-SCREENMAX, [screen frame].size.height - NS_TOP_POS (f), SCREENMAX)); - NSTRACE_POINT ("setFrameTopLeftPoint", pt); - [win setFrameTopLeftPoint: pt]; NSTRACE_RECT ("new frame", [win frame]); @@ -6667,7 +6956,7 @@ not_in_argv (NSString *arg) NSArray *screens = [NSScreen screens]; NSScreen *screen = [screens objectAtIndex: 0]; - NSTRACE ("windowDidMove"); + NSTRACE ("[EmacsView windowDidMove:]"); if (!emacsframe->output_data.ns) return; @@ -6685,7 +6974,7 @@ not_in_argv (NSString *arg) location so set_window_size moves the frame. */ - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame { - NSTRACE (("[windowShouldZoom:win toFrame:" NSTRACE_FMT_RECT "]" + NSTRACE (("[EmacsView windowShouldZoom:toFrame:" NSTRACE_FMT_RECT "]" NSTRACE_FMT_RETURN "YES"), NSTRACE_ARG_RECT (newFrame)); @@ -6704,7 +6993,7 @@ not_in_argv (NSString *arg) // all paths. NSRect result = [sender frame]; - NSTRACE (("[windowWillUseStandardFrame: defaultFrame:" + NSTRACE (("[EmacsView windowWillUseStandardFrame:defaultFrame:" NSTRACE_FMT_RECT "]"), NSTRACE_ARG_RECT (defaultFrame)); NSTRACE_FSTYPE ("fs_state", fs_state); @@ -6817,7 +7106,7 @@ not_in_argv (NSString *arg) - (void)windowDidDeminiaturize: sender { - NSTRACE ("windowDidDeminiaturize"); + NSTRACE ("[EmacsView windowDidDeminiaturize:]"); if (!emacsframe->output_data.ns) return; @@ -6835,7 +7124,7 @@ not_in_argv (NSString *arg) - (void)windowDidExpose: sender { - NSTRACE ("windowDidExpose"); + NSTRACE ("[EmacsView windowDidExpose:]"); if (!emacsframe->output_data.ns) return; @@ -6849,7 +7138,7 @@ not_in_argv (NSString *arg) - (void)windowDidMiniaturize: sender { - NSTRACE ("windowDidMiniaturize"); + NSTRACE ("[EmacsView windowDidMiniaturize:]"); if (!emacsframe->output_data.ns) return; @@ -6874,22 +7163,24 @@ not_in_argv (NSString *arg) - (void)windowWillEnterFullScreen:(NSNotification *)notification { + NSTRACE ("[EmacsView windowWillEnterFullScreen:]"); [self windowWillEnterFullScreen]; } - (void)windowWillEnterFullScreen /* provided for direct calls */ { - NSTRACE ("windowWillEnterFullScreen"); + NSTRACE ("[EmacsView windowWillEnterFullScreen]"); fs_before_fs = fs_state; } - (void)windowDidEnterFullScreen:(NSNotification *)notification { + NSTRACE ("[EmacsView windowDidEnterFullScreen:]"); [self windowDidEnterFullScreen]; } - (void)windowDidEnterFullScreen /* provided for direct calls */ { - NSTRACE ("windowDidEnterFullScreen"); + NSTRACE ("[EmacsView windowDidEnterFullScreen]"); [self setFSValue: FULLSCREEN_BOTH]; if (! [self fsIsNative]) { @@ -6923,12 +7214,13 @@ not_in_argv (NSString *arg) - (void)windowWillExitFullScreen:(NSNotification *)notification { + NSTRACE ("[EmacsView windowWillExitFullScreen:]"); [self windowWillExitFullScreen]; } - (void)windowWillExitFullScreen /* provided for direct calls */ { - NSTRACE ("windowWillExitFullScreen"); + NSTRACE ("[EmacsView windowWillExitFullScreen]"); if (!FRAME_LIVE_P (emacsframe)) { NSTRACE_MSG ("Ignored (frame dead)"); @@ -6940,12 +7232,13 @@ not_in_argv (NSString *arg) - (void)windowDidExitFullScreen:(NSNotification *)notification { + NSTRACE ("[EmacsView windowDidExitFullScreen:]"); [self windowDidExitFullScreen]; } - (void)windowDidExitFullScreen /* provided for direct calls */ { - NSTRACE ("windowDidExitFullScreen"); + NSTRACE ("[EmacsView windowDidExitFullScreen]"); if (!FRAME_LIVE_P (emacsframe)) { NSTRACE_MSG ("Ignored (frame dead)"); @@ -6977,17 +7270,32 @@ not_in_argv (NSString *arg) - (BOOL)isFullscreen { - if (! fs_is_native) return nonfs_window != nil; + BOOL res; + + if (! fs_is_native) + { + res = (nonfs_window != nil); + } + else + { #ifdef HAVE_NATIVE_FS - return ([[self window] styleMask] & NSFullScreenWindowMask) != 0; + res = (([[self window] styleMask] & NSFullScreenWindowMask) != 0); #else - return NO; + res = NO; #endif + } + + NSTRACE ("[EmacsView isFullscreen] " NSTRACE_FMT_RETURN " %d", + (int) res); + + return res; } #ifdef HAVE_NATIVE_FS - (void)updateCollectionBehavior { + NSTRACE ("[EmacsView updateCollectionBehavior]"); + if (! [self isFullscreen]) { NSWindow *win = [self window]; @@ -7011,7 +7319,7 @@ not_in_argv (NSString *arg) NSRect r, wr; NSColor *col; - NSTRACE ("toggleFullScreen"); + NSTRACE ("[EmacsView toggleFullScreen:]"); if (fs_is_native) { @@ -7126,7 +7434,7 @@ not_in_argv (NSString *arg) - (void)handleFS { - NSTRACE ("handleFS"); + NSTRACE ("[EmacsView handleFS]"); if (fs_state != emacsframe->want_fullscreen) { @@ -7177,8 +7485,8 @@ not_in_argv (NSString *arg) - (void) setFSValue: (int)value { - NSTRACE ("setFSValue"); - NSTRACE_FSTYPE ("value", value); + NSTRACE ("[EmacsView setFSValue:" NSTRACE_FMT_FSTYPE "]", + NSTRACE_ARG_FSTYPE(value)); Lisp_Object lval = Qnil; switch (value) @@ -7202,7 +7510,7 @@ not_in_argv (NSString *arg) - (void)mouseEntered: (NSEvent *)theEvent { - NSTRACE ("mouseEntered"); + NSTRACE ("[EmacsView mouseEntered:]"); if (emacsframe) FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time = EV_TIMESTAMP (theEvent); @@ -7213,7 +7521,7 @@ not_in_argv (NSString *arg) { Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL; - NSTRACE ("mouseExited"); + NSTRACE ("[EmacsView mouseExited:]"); if (!hlinfo) return; @@ -7231,7 +7539,7 @@ not_in_argv (NSString *arg) - menuDown: sender { - NSTRACE ("menuDown"); + NSTRACE ("[EmacsView menuDown:]"); if (context_menu_value == -1) context_menu_value = [sender tag]; else @@ -7259,7 +7567,7 @@ not_in_argv (NSString *arg) NSEvent *theEvent; int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS; - NSTRACE ("toolbarClicked"); + NSTRACE ("[EmacsView toolbarClicked:]"); if (!emacs_event) return self; @@ -7282,6 +7590,8 @@ not_in_argv (NSString *arg) - toggleToolbar: (id)sender { + NSTRACE ("[EmacsView toggleToolbar:]"); + if (!emacs_event) return self; @@ -7297,8 +7607,8 @@ not_in_argv (NSString *arg) int x = NSMinX (rect), y = NSMinY (rect); int width = NSWidth (rect), height = NSHeight (rect); - NSTRACE ("drawRect"); - NSTRACE_RECT ("input", rect); + NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]", + NSTRACE_ARG_RECT(rect)); if (!emacsframe || !emacsframe->output_data.ns) return; @@ -7324,7 +7634,7 @@ not_in_argv (NSString *arg) -(NSDragOperation) draggingEntered: (id ) sender { - NSTRACE ("draggingEntered"); + NSTRACE ("[EmacsView draggingEntered:]"); return NSDragOperationGeneric; } @@ -7345,7 +7655,7 @@ not_in_argv (NSString *arg) NSDragOperation op = [sender draggingSourceOperationMask]; int modifiers = 0; - NSTRACE ("performDragOperation"); + NSTRACE ("[EmacsView performDragOperation:]"); if (!emacs_event) return NO; @@ -7445,7 +7755,7 @@ not_in_argv (NSString *arg) - (id) validRequestorForSendType: (NSString *)typeSent returnType: (NSString *)typeReturned { - NSTRACE ("validRequestorForSendType"); + NSTRACE ("[EmacsView validRequestorForSendType:returnType:]"); if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound && typeReturned == nil) { @@ -7478,6 +7788,8 @@ not_in_argv (NSString *arg) NSArray *typesDeclared; Lisp_Object val; + NSTRACE ("[EmacsView writeSelectionToPasteboard:types:]"); + /* We only support NSStringPboardType */ if ([types containsObject:NSStringPboardType] == NO) { return NO; @@ -7507,7 +7819,7 @@ not_in_argv (NSString *arg) - setMiniwindowImage: (BOOL) setMini { id image = [[self window] miniwindowImage]; - NSTRACE ("setMiniwindowImage"); + NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini); /* NOTE: under Cocoa miniwindowImage always returns nil, documentation about "AppleDockIconEnabled" notwithstanding, however the set message @@ -7555,6 +7867,8 @@ not_in_argv (NSString *arg) struct frame *f = SELECTED_FRAME (); struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents); + NSTRACE ("[EmacsWindow accessibilityAttributeValue:]"); + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) return NSAccessibilityTextFieldRole; @@ -7623,7 +7937,7 @@ not_in_argv (NSString *arg) large screen). */ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { - NSTRACE ("constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:", + NSTRACE ("[EmacsWindow constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:]", NSTRACE_ARG_RECT (frameRect)); #ifdef NS_IMPL_COCOA @@ -7640,22 +7954,21 @@ not_in_argv (NSString *arg) #endif #endif - return constrain_frame_rect(frameRect); + return constrain_frame_rect(frameRect, + [(EmacsView *)[self delegate] isFullscreen]); } - (void)performZoom:(id)sender { - NSTRACE ("performZoom"); + NSTRACE ("[EmacsWindow performZoom:]"); return [super performZoom:sender]; } - (void)zoom:(id)sender { - struct frame * f = SELECTED_FRAME (); - - NSTRACE ("zoom"); + NSTRACE ("[EmacsWindow zoom:]"); ns_update_auto_hide_menu_bar(); @@ -7668,9 +7981,10 @@ not_in_argv (NSString *arg) // the menu-bar. [super zoom:sender]; -#elsif 0 +#elif 0 // Native zoom done using the standard zoom animation, plus an - // explicit resize to cover the full screen. + // explicit resize to cover the full screen, except the menu-bar and + // dock, if present. [super zoom:sender]; // After the native zoom, resize the resulting frame to fill the @@ -7690,6 +8004,9 @@ not_in_argv (NSString *arg) NSTRACE_FSTYPE ("fullscreenState", fs_state); NSRect sr = [screen frame]; + struct EmacsMargins margins + = ns_screen_margins_ignoring_hidden_dock(screen); + NSRect wr = [self frame]; NSTRACE_RECT ("Rect after zoom", wr); @@ -7698,15 +8015,15 @@ not_in_argv (NSString *arg) if (fs_state == FULLSCREEN_MAXIMIZED || fs_state == FULLSCREEN_HEIGHT) { - newWr.origin.x = 0; - newWr.size.height = sr.size.height - ns_menu_bar_height(screen); + newWr.origin.y = sr.origin.y + margins.bottom; + newWr.size.height = sr.size.height - margins.top - margins.bottom; } if (fs_state == FULLSCREEN_MAXIMIZED || fs_state == FULLSCREEN_WIDTH) { - newWr.origin.y = 0; - newWr.size.width = sr.size.width; + newWr.origin.x = sr.origin.x + margins.left; + newWr.size.width = sr.size.width - margins.right - margins.left; } if (newWr.size.width != wr.size.width @@ -7714,18 +8031,25 @@ not_in_argv (NSString *arg) || newWr.origin.x != wr.origin.x || newWr.origin.y != wr.origin.y) { - NSTRACE_RECT ("Corrected rect", newWr); + NSTRACE_MSG ("New frame different"); [self setFrame: newWr display: NO]; } } #else - // Non-native zoom which is done instantaneously. The resulting frame - // covers the entire screen, except the menu-bar, if present. + // Non-native zoom which is done instantaneously. The resulting + // frame covers the entire screen, except the menu-bar and dock, if + // present. NSScreen * screen = [self screen]; if (screen != nil) { NSRect sr = [screen frame]; - sr.size.height -= ns_menu_bar_height (screen); + struct EmacsMargins margins + = ns_screen_margins_ignoring_hidden_dock(screen); + + sr.size.height -= (margins.top + margins.bottom); + sr.size.width -= (margins.left + margins.right); + sr.origin.x += margins.left; + sr.origin.y += margins.bottom; sr = [[self delegate] windowWillUseStandardFrame:self defaultFrame:sr]; @@ -7734,6 +8058,33 @@ not_in_argv (NSString *arg) #endif } +- (void)setFrame:(NSRect)windowFrame + display:(BOOL)displayViews +{ + NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT " display:%d]", + NSTRACE_ARG_RECT (windowFrame), displayViews); + + [super setFrame:windowFrame display:displayViews]; +} + +- (void)setFrame:(NSRect)windowFrame + display:(BOOL)displayViews + animate:(BOOL)performAnimation +{ + NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT + " display:%d performAnimation:%d]", + NSTRACE_ARG_RECT (windowFrame), displayViews, performAnimation); + + [super setFrame:windowFrame display:displayViews animate:performAnimation]; +} + +- (void)setFrameTopLeftPoint:(NSPoint)point +{ + NSTRACE ("[EmacsWindow setFrameTopLeftPoint:" NSTRACE_FMT_POINT "]", + NSTRACE_ARG_POINT (point)); + + [super setFrameTopLeftPoint:point]; +} @end /* EmacsWindow */ @@ -7779,12 +8130,15 @@ not_in_argv (NSString *arg) return r; } - - initFrame: (NSRect )r window: (Lisp_Object)nwin { - NSTRACE ("EmacsScroller_initFrame"); + NSTRACE ("[EmacsScroller initFrame: window:]"); + + if (r.size.width > r.size.height) + horizontal = YES; + else + horizontal = NO; - r.size.width = [EmacsScroller scrollerWidth]; [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/]; [self setContinuous: YES]; [self setEnabled: YES]; @@ -7800,9 +8154,12 @@ not_in_argv (NSString *arg) window = XWINDOW (nwin); condemned = NO; - pixel_height = NSHeight (r); - if (pixel_height == 0) pixel_height = 1; - min_portion = 20 / pixel_height; + if (horizontal) + pixel_length = NSWidth (r); + else + pixel_length = NSHeight (r); + if (pixel_length == 0) pixel_length = 1; + min_portion = 20 / pixel_length; frame = XFRAME (window->frame); if (FRAME_LIVE_P (frame)) @@ -7828,11 +8185,15 @@ not_in_argv (NSString *arg) - (void)setFrame: (NSRect)newRect { - NSTRACE ("EmacsScroller_setFrame"); + NSTRACE ("[EmacsScroller setFrame:]"); + /* block_input (); */ - pixel_height = NSHeight (newRect); - if (pixel_height == 0) pixel_height = 1; - min_portion = 20 / pixel_height; + if (horizontal) + pixel_length = NSWidth (newRect); + else + pixel_length = NSHeight (newRect); + if (pixel_length == 0) pixel_length = 1; + min_portion = 20 / pixel_length; [super setFrame: newRect]; /* unblock_input (); */ } @@ -7840,9 +8201,14 @@ not_in_argv (NSString *arg) - (void)dealloc { - NSTRACE ("EmacsScroller_dealloc"); + NSTRACE ("[EmacsScroller dealloc]"); if (window) - wset_vertical_scroll_bar (window, Qnil); + { + if (horizontal) + wset_horizontal_scroll_bar (window, Qnil); + else + wset_vertical_scroll_bar (window, Qnil); + } window = 0; [super dealloc]; } @@ -7850,7 +8216,7 @@ not_in_argv (NSString *arg) - condemn { - NSTRACE ("condemn"); + NSTRACE ("[EmacsScroller condemn]"); condemned =YES; return self; } @@ -7858,7 +8224,7 @@ not_in_argv (NSString *arg) - reprieve { - NSTRACE ("reprieve"); + NSTRACE ("[EmacsScroller reprieve]"); condemned =NO; return self; } @@ -7866,7 +8232,7 @@ not_in_argv (NSString *arg) -(bool)judge { - NSTRACE ("judge"); + NSTRACE ("[EmacsScroller judge]"); bool ret = condemned; if (condemned) { @@ -7877,7 +8243,12 @@ not_in_argv (NSString *arg) if (view != nil) view->scrollbarsNeedingUpdate++; if (window) - wset_vertical_scroll_bar (window, Qnil); + { + if (horizontal) + wset_horizontal_scroll_bar (window, Qnil); + else + wset_vertical_scroll_bar (window, Qnil); + } window = 0; [self removeFromSuperview]; [self release]; @@ -7890,7 +8261,7 @@ not_in_argv (NSString *arg) - (void)resetCursorRects { NSRect visible = [self visibleRect]; - NSTRACE ("resetCursorRects"); + NSTRACE ("[EmacsScroller resetCursorRects]"); if (!NSIsEmptyRect (visible)) [self addCursorRect: visible cursor: [NSCursor arrowCursor]]; @@ -7908,7 +8279,7 @@ not_in_argv (NSString *arg) - setPosition: (int)position portion: (int)portion whole: (int)whole { - NSTRACE ("setPosition"); + NSTRACE ("[EmacsScroller setPosition:portion:whole:]"); em_position = position; em_portion = portion; @@ -7927,7 +8298,7 @@ not_in_argv (NSString *arg) { float pos; CGFloat por; - portion = max ((float)whole*min_portion/pixel_height, portion); + portion = max ((float)whole*min_portion/pixel_length, portion); pos = (float)position / (whole - portion); por = (CGFloat)portion/whole; #ifdef NS_IMPL_COCOA @@ -7945,6 +8316,9 @@ not_in_argv (NSString *arg) - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e { Lisp_Object win; + + NSTRACE ("[EmacsScroller sendScrollEventAtLoc:fromEvent:]"); + if (!emacs_event) return; @@ -7954,10 +8328,20 @@ not_in_argv (NSString *arg) XSETWINDOW (win, window); emacs_event->frame_or_window = win; emacs_event->timestamp = EV_TIMESTAMP (e); - emacs_event->kind = SCROLL_BAR_CLICK_EVENT; emacs_event->arg = Qnil; - XSETINT (emacs_event->x, loc * pixel_height); - XSETINT (emacs_event->y, pixel_height-20); + + if (horizontal) + { + emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT; + XSETINT (emacs_event->x, em_whole * loc / pixel_length); + XSETINT (emacs_event->y, em_whole); + } + else + { + emacs_event->kind = SCROLL_BAR_CLICK_EVENT; + XSETINT (emacs_event->x, loc); + XSETINT (emacs_event->y, pixel_length-20); + } if (q_event_ptr) { @@ -7978,6 +8362,8 @@ not_in_argv (NSString *arg) NSPoint p = [[self window] mouseLocationOutsideOfEventStream]; BOOL inKnob = [self testPart: p] == NSScrollerKnob; + NSTRACE ("[EmacsScroller repeatScroll:]"); + /* clear timer if need be */ if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY) { @@ -8013,20 +8399,20 @@ not_in_argv (NSString *arg) CGFloat inc = 0.0, loc, kloc, pos; int edge = 0; - NSTRACE ("EmacsScroller_mouseDown"); + NSTRACE ("[EmacsScroller mouseDown:]"); switch (part) { case NSScrollerDecrementPage: - last_hit_part = scroll_bar_above_handle; inc = -1.0; break; + last_hit_part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle; break; case NSScrollerIncrementPage: - last_hit_part = scroll_bar_below_handle; inc = 1.0; break; + last_hit_part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle; break; case NSScrollerDecrementLine: - last_hit_part = scroll_bar_up_arrow; inc = -0.1; break; + last_hit_part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow; break; case NSScrollerIncrementLine: - last_hit_part = scroll_bar_down_arrow; inc = 0.1; break; + last_hit_part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow; break; case NSScrollerKnob: - last_hit_part = scroll_bar_handle; break; + last_hit_part = horizontal ? scroll_bar_horizontal_handle : scroll_bar_handle; break; case NSScrollerKnobSlot: /* GNUstep-only */ last_hit_part = scroll_bar_move_ratio; break; default: /* NSScrollerNoPart? */ @@ -8035,36 +8421,34 @@ not_in_argv (NSString *arg) return; } - if (inc != 0.0) - { - pos = 0; /* ignored */ - - /* set a timer to repeat, as we can't let superclass do this modally */ - scroll_repeat_entry - = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY - target: self - selector: @selector (repeatScroll:) - userInfo: 0 - repeats: YES] - retain]; - } - else + if (part == NSScrollerKnob || part == NSScrollerKnobSlot) { /* handle, or on GNUstep possibly slot */ NSEvent *fake_event; + int length; /* compute float loc in slot and mouse offset on knob */ sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot] toView: nil]; - loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr)); + if (horizontal) + { + length = NSWidth (sr); + loc = ([e locationInWindow].x - NSMinX (sr)); + } + else + { + length = NSHeight (sr); + loc = length - ([e locationInWindow].y - NSMinY (sr)); + } + if (loc <= 0.0) { loc = 0.0; edge = -1; } - else if (loc >= NSHeight (sr)) + else if (loc >= length) { - loc = NSHeight (sr); + loc = length; edge = 1; } @@ -8074,17 +8458,16 @@ not_in_argv (NSString *arg) { kr = [self convertRect: [self rectForPart: NSScrollerKnob] toView: nil]; - kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr)); + if (horizontal) + kloc = ([e locationInWindow].x - NSMinX (kr)); + else + kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr)); } last_mouse_offset = kloc; - /* if knob, tell emacs a location offset by knob pos - (to indicate top of handle) */ - if (part == NSScrollerKnob) - pos = (loc - last_mouse_offset) / NSHeight (sr); - else - /* else this is a slot click on GNUstep: go straight there */ - pos = loc / NSHeight (sr); + if (part != NSScrollerKnob) + /* this is a slot click on GNUstep: go straight there */ + pos = loc; /* send a fake mouse-up to super to preempt modal -trackKnob: mode */ fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp @@ -8098,6 +8481,19 @@ not_in_argv (NSString *arg) pressure: [e pressure]]; [super mouseUp: fake_event]; } + else + { + pos = 0; /* ignored */ + + /* set a timer to repeat, as we can't let superclass do this modally */ + scroll_repeat_entry + = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY + target: self + selector: @selector (repeatScroll:) + userInfo: 0 + repeats: YES] + retain]; + } if (part != NSScrollerKnob) [self sendScrollEventAtLoc: pos fromEvent: e]; @@ -8109,29 +8505,42 @@ not_in_argv (NSString *arg) { NSRect sr; double loc, pos; + int length; - NSTRACE ("EmacsScroller_mouseDragged"); + NSTRACE ("[EmacsScroller mouseDragged:]"); sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot] toView: nil]; - loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr)); + + if (horizontal) + { + length = NSWidth (sr); + loc = ([e locationInWindow].x - NSMinX (sr)); + } + else + { + length = NSHeight (sr); + loc = length - ([e locationInWindow].y - NSMinY (sr)); + } if (loc <= 0.0) { loc = 0.0; } - else if (loc >= NSHeight (sr) + last_mouse_offset) + else if (loc >= length + last_mouse_offset) { - loc = NSHeight (sr) + last_mouse_offset; + loc = length + last_mouse_offset; } - pos = (loc - last_mouse_offset) / NSHeight (sr); + pos = (loc - last_mouse_offset); [self sendScrollEventAtLoc: pos fromEvent: e]; } - (void)mouseUp: (NSEvent *)e { + NSTRACE ("[EmacsScroller mouseUp:]"); + if (scroll_repeat_entry) { [scroll_repeat_entry invalidate]; @@ -8145,6 +8554,8 @@ not_in_argv (NSString *arg) /* treat scrollwheel events in the bar as though they were in the main window */ - (void) scrollWheel: (NSEvent *)theEvent { + NSTRACE ("[EmacsScroller scrollWheel:]"); + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame); [view mouseDown: theEvent]; }