X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/914e743b60af339ae577385a18685f8a40f9fe8f..ab422c4d6899b1442cb6954c1829c1fb656b006c:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index 2df0e1a1ad..d9ebf714a9 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1,7 +1,7 @@ /* NeXT/Open/GNUstep / MacOSX communication module. -Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2012 - Free Software Foundation, Inc. +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 Free Software +Foundation, Inc. This file is part of GNU Emacs. @@ -55,7 +55,6 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "ccl.h" #include "termhooks.h" -#include "termopts.h" #include "termchar.h" #include "window.h" @@ -183,7 +182,6 @@ static int ns_window_num = 0; static NSRect uRect; #endif static BOOL gsaved = NO; -BOOL ns_in_resize = NO; static BOOL ns_fake_keydown = NO; int ns_tmp_flags; /* FIXME */ struct nsfont_info *ns_tmp_font; /* FIXME */ @@ -192,7 +190,8 @@ static BOOL ns_menu_bar_is_hidden = NO; /* event loop */ static BOOL send_appdefined = YES; -static NSEvent *last_appdefined_event = 0; +#define NO_APPDEFINED_DATA (-8) +static int last_appdefined_event_data = NO_APPDEFINED_DATA; static NSTimer *timed_entry = 0; static NSTimer *scroll_repeat_entry = nil; static fd_set select_readfds, select_writefds; @@ -210,6 +209,13 @@ static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; static BOOL ns_do_open_file = NO; +static struct { + struct input_event *q; + int nr, cap; +} hold_event_q = { + NULL, 0, 0 +}; + /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ #define NS_FUNCTION_KEY_MASK 0x800000 #define NSLeftControlKeyMask (0x000001 | NSControlKeyMask) @@ -275,7 +281,7 @@ static BOOL ns_do_open_file = NO; kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ } \ else \ - kbd_buffer_store_event (emacs_event); \ + hold_event (emacs_event); \ EVENT_INIT (*emacs_event); \ ns_send_appdefined (-1); \ } @@ -294,6 +300,22 @@ void x_set_frame_alpha (struct frame *f); ========================================================================== */ +static void +hold_event (struct input_event *event) +{ + if (hold_event_q.nr == hold_event_q.cap) + { + if (hold_event_q.cap == 0) hold_event_q.cap = 10; + else hold_event_q.cap *= 2; + hold_event_q.q = (struct input_event *) + xrealloc (hold_event_q.q, hold_event_q.cap * sizeof (*hold_event_q.q)); + } + + hold_event_q.q[hold_event_q.nr++] = *event; + /* Make sure ns_read_socket is called, i.e. we have input. */ + kill (0, SIGIO); + send_appdefined = YES; +} static Lisp_Object append2 (Lisp_Object list, Lisp_Object item) @@ -493,17 +515,6 @@ ns_release_autorelease_pool (void *pool) ========================================================================== */ -static NSRect -ns_resize_handle_rect (NSWindow *window) -{ - NSRect r = [window frame]; - r.origin.x = r.size.width - RESIZE_HANDLE_SIZE; - r.origin.y = 0; - r.size.width = r.size.height = RESIZE_HANDLE_SIZE; - return r; -} - - // // Window constraining // ------------------- @@ -581,9 +592,6 @@ ns_menu_bar_should_be_hidden (void) static void ns_update_auto_hide_menu_bar (void) { -#ifndef MAC_OS_X_VERSION_10_6 -#define MAC_OS_X_VERSION_10_6 1060 -#endif #ifdef NS_IMPL_COCOA #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 block_input (); @@ -1068,8 +1076,23 @@ x_make_frame_visible (struct frame *f) if this ends up the case again, comment this out again. */ if (!FRAME_VISIBLE_P (f)) { + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); f->async_visible = 1; ns_raise_frame (f); + +#ifdef NEW_STYLE_FS + /* Making a new frame from a fullscreen frame will make the new frame + fullscreen also. So skip handleFS as this will print an error. */ + if (f->want_fullscreen == FULLSCREEN_BOTH + && ([[view window] styleMask] & NSFullScreenWindowMask) != 0) + return; +#endif + if (f->want_fullscreen != FULLSCREEN_NONE) + { + block_input (); + [view handleFS]; + unblock_input (); + } } } @@ -1315,8 +1338,20 @@ static void ns_fullscreen_hook (FRAME_PTR f) { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); - + if (! f->async_visible) return; +#ifndef NEW_STYLE_FS + if (f->want_fullscreen == FULLSCREEN_BOTH) + { + /* Old style fs don't initiate correctly if created from + init/default-frame alist, so use a timer (not nice...). + */ + [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view + selector: @selector (handleFS) + userInfo: nil repeats: NO]; + return; + } +#endif block_input (); [view handleFS]; @@ -1956,8 +1991,6 @@ ns_clear_frame (struct frame *f) NSRect r; NSTRACE (ns_clear_frame); - if (ns_in_resize) - return; /* comes on initial frame because we have after-make-frame-functions = select-frame */ @@ -1977,10 +2010,6 @@ ns_clear_frame (struct frame *f) NSRectFill (r); ns_unfocus (f); -#ifdef NS_IMPL_COCOA - [[view window] display]; /* redraw resize handle */ -#endif - /* as of 2006/11 or so this is now needed */ ns_redraw_scroll_bars (f); unblock_input (); @@ -2006,35 +2035,8 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) ns_focus (f, &r, 1); [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; -#ifdef NS_IMPL_COCOA - { - /* clip out the resize handle */ - NSWindow *window = [FRAME_NS_VIEW (f) window]; - NSRect ir - = [view convertRect: ns_resize_handle_rect (window) fromView: nil]; - - ir = NSIntersectionRect (r, ir); - if (NSIsEmptyRect (ir)) - { -#endif - NSRectFill (r); -#ifdef NS_IMPL_COCOA - } - else - { - NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */ - r1.size.height -= ir.size.height; - r2.origin.y += r1.size.height; - r2.size.width -= ir.size.width; - r2.size.height = ir.size.height; - NSRectFill (r1); - NSRectFill (r2); - } - } -#endif - ns_unfocus (f); return; } @@ -2996,8 +2998,10 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) { #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height); + NSRect ir = NSMakeRect (s->slice.x, s->slice.y, + s->slice.width, s->slice.height); [img drawInRect: dr - fromRect: NSZeroRect + fromRect: ir operation: NSCompositeSourceOver fraction: 1.0 respectFlipped: YES @@ -3368,6 +3372,15 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) if ([NSApp modalWindow] != nil) return -1; + if (hold_event_q.nr > 0) + { + int i; + for (i = 0; i < hold_event_q.nr; ++i) + kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit); + hold_event_q.nr = 0; + return i; + } + block_input (); n_emacs_events_pending = 0; EVENT_INIT (ev); @@ -3427,15 +3440,25 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, -------------------------------------------------------------------------- */ { int result; - NSEvent *ev; - int k, nr = 0; + int t, k, nr = 0; struct input_event event; char c; /* NSTRACE (ns_select); */ - for (k = 0; readfds && k < nfds+1; k++) - if (FD_ISSET(k, readfds)) ++nr; + if (hold_event_q.nr > 0) + { + /* We already have events pending. */ + kill (0, SIGIO); + errno = EINTR; + return -1; + } + + for (k = 0; k < nfds+1; k++) + { + if (readfds && FD_ISSET(k, readfds)) ++nr; + if (writefds && FD_ISSET(k, writefds)) ++nr; + } if (NSApp == nil || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) @@ -3509,16 +3532,11 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, } unblock_input (); - ev = last_appdefined_event; + t = last_appdefined_event_data; - if (ev) + if (t != NO_APPDEFINED_DATA) { - int t; - if ([ev type] != NSApplicationDefined) - emacs_abort (); - - t = [ev data1]; - last_appdefined_event = 0; + last_appdefined_event_data = NO_APPDEFINED_DATA; if (t == -2) { @@ -4210,6 +4228,11 @@ ns_term_init (Lisp_Object display_name) NSColorPboardType, NSFontPboardType, nil] retain]; +#ifndef NEW_STYLE_FS + /* If fullscreen is in init/default-frame-alist, focus isn't set + right for fullscreen windows, so set this. */ + [NSApp activateIgnoringOtherApps:YES]; +#endif [NSApp run]; ns_do_open_file = YES; @@ -4282,34 +4305,6 @@ ns_term_shutdown (int sig) return; } -#ifdef NS_IMPL_COCOA - /* pass mouse down in resize handle and subsequent drags directly to - EmacsWindow so we can generate continuous redisplays */ - if (ns_in_resize) - { - if (type == NSLeftMouseDragged) - { - [window mouseDragged: theEvent]; - return; - } - else if (type == NSLeftMouseUp) - { - [window mouseUp: theEvent]; - return; - } - } - else if (type == NSLeftMouseDown) - { - NSRect r = ns_resize_handle_rect (window); - if (NSPointInRect ([theEvent locationInWindow], r)) - { - ns_in_resize = YES; - [window mouseDown: theEvent]; - return; - } - } -#endif - if (type == NSApplicationDefined) { /* Events posted by ns_send_appdefined interrupt the run loop here. @@ -4318,7 +4313,7 @@ ns_term_shutdown (int sig) modal loop. Just defer it until later. */ if ([NSApp modalWindow] == nil) { - last_appdefined_event = theEvent; + last_appdefined_event_data = [theEvent data1]; [self stop: self]; } else @@ -4571,7 +4566,7 @@ not_in_argv (NSString *arg) if (waiting) { SELECT_TYPE fds; - + FD_ZERO (&fds); FD_SET (selfds[0], &fds); result = select (selfds[0]+1, &fds, NULL, NULL, NULL); if (result > 0) @@ -5505,10 +5500,17 @@ not_in_argv (NSString *arg) - (void)windowDidResize: (NSNotification *)notification { + +#if !defined (NEW_STYLE_FS) && ! defined (NS_IMPL_GNUSTEP) + NSWindow *theWindow = [notification object]; + /* We can get notification on the non-FS window when in fullscreen mode. */ + if ([self window] != theWindow) return; +#endif + #ifdef NS_IMPL_GNUSTEP NSWindow *theWindow = [notification object]; - /* in GNUstep, at least currently, it's possible to get a didResize + /* In GNUstep, at least currently, it's possible to get a didResize without getting a willResize.. therefore we need to act as if we got the willResize now */ NSSize sz = [theWindow frame].size; @@ -5526,20 +5528,10 @@ not_in_argv (NSString *arg) } #endif /* NS_IMPL_COCOA */ - /* Avoid loop under GNUstep due to call at beginning of this function. - (x_set_window_size causes a resize which causes - a "windowDidResize" which calls x_set_window_size). */ -#ifndef NS_IMPL_GNUSTEP if (cols > 0 && rows > 0) { - if (ns_in_resize) - x_set_window_size (emacsframe, 0, cols, rows); - else - { - [self updateFrameSize: YES]; - } + [self updateFrameSize: YES]; } -#endif ns_send_appdefined (-1); } @@ -5661,7 +5653,7 @@ not_in_argv (NSString *arg) wr = [win frame]; bwidth = f->border_width = wr.size.width - r.size.width; - tbar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; + tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; [win setAcceptsMouseMovedEvents: YES]; [win setDelegate: self]; @@ -5870,8 +5862,16 @@ not_in_argv (NSString *arg) - (void)windowDidEnterFullScreen:(NSNotification *)notification { [self setFSValue: FULLSCREEN_BOTH]; -#ifndef NEW_STYLE_FS +#ifdef NEW_STYLE_FS + // Fix bad background. + if ([toolbar isVisible]) + { + [toolbar setVisible:NO]; + [toolbar setVisible:YES]; + } +#else [self windowDidBecomeKey:notification]; + [nonfs_window orderOut:self]; #endif } @@ -5891,11 +5891,6 @@ not_in_argv (NSString *arg) - (void)toggleFullScreen: (id)sender { - /* Bugs remain: - 1) Having fullscreen in initial/default frame alist. - 2) Fullscreen in default frame alist only applied to first frame. - */ - #ifdef NEW_STYLE_FS [[self window] toggleFullScreen:sender]; #else @@ -5904,7 +5899,7 @@ not_in_argv (NSString *arg) isEqual:[[NSScreen screens] objectAtIndex:0]]; struct frame *f = emacsframe; NSSize sz; - NSRect r; + NSRect r, wr = [w frame]; NSColor *col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f); @@ -5930,7 +5925,7 @@ not_in_argv (NSString *arg) } fw = [[EmacsFSWindow alloc] - initWithContentRect:[w contentRectForFrameRect:[w frame]] + initWithContentRect:[w contentRectForFrameRect:wr] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES @@ -5938,9 +5933,7 @@ not_in_argv (NSString *arg) [fw setContentView:[w contentView]]; [fw setTitle:[w title]]; - [fw makeKeyAndOrderFront:NSApp]; [fw setDelegate:self]; - [fw makeFirstResponder:self]; [fw setAcceptsMouseMovedEvents: YES]; [fw useOptimizedDrawing: YES]; [fw setResizeIncrements: sz]; @@ -5950,18 +5943,26 @@ not_in_argv (NSString *arg) f->border_width = 0; FRAME_NS_TITLEBAR_HEIGHT (f) = 0; + tobar_height = FRAME_TOOLBAR_HEIGHT (f); + FRAME_TOOLBAR_HEIGHT (f) = 0; + FRAME_EXTERNAL_TOOL_BAR (f) = 0; nonfs_window = w; + [self windowWillEnterFullScreen:nil]; + [fw makeKeyAndOrderFront:NSApp]; + [fw makeFirstResponder:self]; [w orderOut:self]; r = [fw frameRectForContentRect:[[fw screen] frame]]; [fw setFrame: r display:YES animate:YES]; [self windowDidEnterFullScreen:nil]; + [fw display]; } else { fw = w; w = nonfs_window; + nonfs_window = nil; if (onFirstScreen) { @@ -5978,9 +5979,12 @@ not_in_argv (NSString *arg) [w setBackgroundColor: col]; if ([col alphaComponent] != 1.0) [w setOpaque: NO]; - + f->border_width = bwidth; - FRAME_NS_TITLEBAR_HEIGHT (f) = tbar_height; + FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height; + FRAME_TOOLBAR_HEIGHT (f) = tobar_height; + if (tobar_height) + FRAME_EXTERNAL_TOOL_BAR (f) = 1; [self windowWillExitFullScreen:nil]; [fw setFrame: [w frame] display:YES animate:YES]; @@ -6028,7 +6032,7 @@ not_in_argv (NSString *arg) } break; } - + emacsframe->want_fullscreen = FULLSCREEN_NONE; } @@ -6152,7 +6156,7 @@ not_in_argv (NSString *arg) NSTRACE (drawRect); - if (!emacsframe || !emacsframe->output_data.ns || ns_in_resize) + if (!emacsframe || !emacsframe->output_data.ns) return; ns_clear_frame_area (emacsframe, x, y, width, height); @@ -6489,60 +6493,6 @@ not_in_argv (NSString *arg) return [super constrainFrameRect:frameRect toScreen:screen]; } - -/* called only on resize clicks by special case in EmacsApp-sendEvent */ -- (void)mouseDown: (NSEvent *)theEvent -{ - if (ns_in_resize) - { - NSSize size = [[theEvent window] frame].size; - grabOffset = [theEvent locationInWindow]; - grabOffset.x = size.width - grabOffset.x; - } - else - [super mouseDown: theEvent]; -} - - -/* stop resizing */ -- (void)mouseUp: (NSEvent *)theEvent -{ - if (ns_in_resize) - { - struct frame *f = ((EmacsView *)[self delegate])->emacsframe; - ns_in_resize = NO; - ns_set_name_as_filename (f); - [self display]; - ns_send_appdefined (-1); - } - else - [super mouseUp: theEvent]; -} - - -/* send resize events */ -- (void)mouseDragged: (NSEvent *)theEvent -{ - if (ns_in_resize) - { - NSPoint p = [theEvent locationInWindow]; - NSSize size, vettedSize, origSize = [self frame].size; - - size.width = p.x + grabOffset.x; - size.height = origSize.height - p.y + grabOffset.y; - - if (size.width == origSize.width && size.height == origSize.height) - return; - - vettedSize = [[self delegate] windowWillResize: self toSize: size]; - [[NSNotificationCenter defaultCenter] - postNotificationName: NSWindowDidResizeNotification - object: self]; - } - else - [super mouseDragged: theEvent]; -} - @end /* EmacsWindow */ @@ -6553,6 +6503,11 @@ not_in_argv (NSString *arg) return YES; } +- (BOOL)canBecomeMainWindow +{ + return YES; +} + @end /* ========================================================================== @@ -6728,6 +6683,12 @@ not_in_argv (NSString *arg) [self setFloatValue: pos knobProportion: por]; #endif } + + /* Events may come here even if the event loop is not running. + If we don't enter the event loop, the scroll bar will not update. + So send SIGIO to ourselves. */ + if (apploopnr == 0) kill (0, SIGIO); + return self; } @@ -6768,7 +6729,7 @@ not_in_argv (NSString *arg) kbd_buffer_store_event_hold (emacs_event, q_event_ptr); } else - kbd_buffer_store_event (emacs_event); + hold_event (emacs_event); EVENT_INIT (*emacs_event); ns_send_appdefined (-1); } @@ -7168,7 +7129,7 @@ allowing it to be used at a lower level for accented character entry."); ns_function_modifier = Qnone; DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, - "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above."); + "Non-nil (the default) means to render text antialiased."); ns_antialias_text = Qt; DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,