0x1B, 0x1B /* escape */
};
-
static Lisp_Object Qmodifier_value;
Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper, Qnone;
extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
+static Lisp_Object QUTF8_STRING;
+
/* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
the maximum font size to NOT antialias. On GNUstep there is currently
no way to control this behavior. */
/* display update */
NSPoint last_mouse_motion_position;
static NSRect last_mouse_glyph;
-static unsigned long last_mouse_movement_time = 0;
+static Time last_mouse_movement_time = 0;
static Lisp_Object last_mouse_motion_frame;
static EmacsScroller *last_mouse_scroll_bar = nil;
static struct frame *ns_updating_frame;
static BOOL ns_fake_keydown = NO;
int ns_tmp_flags; /* FIXME */
struct nsfont_info *ns_tmp_font; /* FIXME */
+static BOOL ns_menu_bar_is_hidden = NO;
/*static int debug_lock = 0; */
/* event loop */
*ns_pending_service_args;
static BOOL inNsSelect = 0;
-/* Convert modifiers in a NeXTSTEP event to emacs style modifiers. */
+/* Convert modifiers in a NeXTstep event to emacs style modifiers. */
#define NS_FUNCTION_KEY_MASK 0x800000
#define NSLeftControlKeyMask (0x000001 | NSControlKeyMask)
#define NSRightControlKeyMask (0x002000 | NSControlKeyMask)
}
+//
+// Window constraining
+// -------------------
+//
+// To ensure that the windows are not placed under the menu bar, they
+// are typically moved by the call-back constrainFrameRect. However,
+// by overriding it, it's possible to inhibit this, leaving the window
+// in it's original position.
+//
+// It's possible to hide the menu bar. However, technically, it's only
+// possible to hide it when the application is active. To ensure that
+// this work properly, the menu bar and window constraining are
+// deferred until the application becomes active.
+//
+// Even though it's not possible to manually move a window above the
+// top of the screen, it is allowed if it's done programmatically,
+// when the menu is hidden. This allows the editable area to cover the
+// full screen height.
+//
+// Test cases
+// ----------
+//
+// Use the following extra files:
+//
+// init.el:
+// ;; Hide menu and place frame slightly above the top of the screen.
+// (setq ns-auto-hide-menu-bar t)
+// (set-frame-position (selected-frame) 0 -20)
+//
+// Test 1:
+//
+// emacs -Q -l init.el
+//
+// Result: No menu bar, and the title bar should be above the screen.
+//
+// Test 2:
+//
+// emacs -Q
+//
+// Result: Menu bar visible, frame placed immediately below the menu.
+//
+
+static void
+ns_constrain_all_frames (void)
+{
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_NS_P (f))
+ {
+ NSView *view = FRAME_NS_VIEW (f);
+ /* This no-op will trigger the default window placing
+ * constriant system. */
+ f->output_data.ns->dont_constrain = 0;
+ [[view window] setFrameOrigin:[[view window] frame].origin];
+ }
+ }
+}
+
+
+/* True, if the menu bar should be hidden. */
+
+static BOOL
+ns_menu_bar_should_be_hidden (void)
+{
+ return !NILP (ns_auto_hide_menu_bar)
+ && [NSApp respondsToSelector:@selector(setPresentationOptions:)];
+}
+
+
+/* Show or hide the menu bar, based on user setting. */
+
+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;
+
+ NSTRACE (ns_update_auto_hide_menu_bar);
+
+ if (NSApp != nil
+ && [NSApp isActive]
+ && [NSApp respondsToSelector:@selector(setPresentationOptions:)])
+ {
+ // Note, "setPresentationOptions" triggers an error unless the
+ // application is active.
+ BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden ();
+
+ if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden)
+ {
+ NSApplicationPresentationOptions options
+ = NSApplicationPresentationAutoHideDock;
+
+ if (menu_bar_should_be_hidden)
+ options |= NSApplicationPresentationAutoHideMenuBar;
+
+ [NSApp setPresentationOptions: options];
+
+ ns_menu_bar_is_hidden = menu_bar_should_be_hidden;
+
+ if (!ns_menu_bar_is_hidden)
+ {
+ ns_constrain_all_frames ();
+ }
+ }
+ }
+
+ UNBLOCK_INPUT;
+#endif
+#endif
+}
+
+
static void
ns_update_begin (struct frame *f)
/* --------------------------------------------------------------------------
NSView *view = FRAME_NS_VIEW (f);
NSTRACE (ns_update_begin);
+ ns_update_auto_hide_menu_bar ();
+
ns_updating_frame = f;
[view lockFocus];
: f->left_pos;
/* We use visibleFrame here to take menu bar into account.
Ideally we should also adjust left/top with visibleFrame.origin. */
-
+
f->top_pos = f->size_hint_flags & YNegative
? ([screen visibleFrame].size.height + f->top_pos
- FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
FRAME_TOOLBAR_HEIGHT (f) = 0;
wr.size.width = pixelwidth + f->border_width;
- wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f)
+ wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f)
+ FRAME_TOOLBAR_HEIGHT (f);
/* Do not try to constrain to this screen. We may have multiple
static void
ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
- unsigned long *time)
+ Time *time)
/* --------------------------------------------------------------------------
External (hook): inform emacs about mouse position and hit parts.
If a scrollbar is being dragged, set bar_window, part, x, y, time.
int x, int y, int cursor_type, int cursor_width,
int on_p, int active_p)
/* --------------------------------------------------------------------------
- External call (RIF): draw cursor
- (modeled after x_draw_window_cursor
- FIXME: cursor_width is effectively bogus -- it sometimes gets set
- in xdisp.c set_frame_cursor_types, sometimes left uninitialized;
- DON'T USE IT (no other terms do)
+ External call (RIF): draw cursor.
+ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
-------------------------------------------------------------------------- */
{
NSRect r, s;
- int fx, fy, h;
+ int fx, fy, h, cursor_height;
struct frame *f = WINDOW_XFRAME (w);
struct glyph *phys_cursor_glyph;
int overspill;
and mini-buffer. */
NSTRACE (dumpcursor);
-//fprintf(stderr, "drawcursor (%d,%d) activep = %d\tonp = %d\tc_type = %d\twidth = %d\n",x,y, active_p,on_p,cursor_type,cursor_width);
if (!on_p)
return;
return;
}
+ /* We draw the cursor (with NSRectFill), then draw the glyph on top
+ (other terminals do it the other way round). We must set
+ w->phys_cursor_width to the cursor width. For bar cursors, that
+ is CURSOR_WIDTH; for box cursors, it is the glyph width. */
get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
+ /* The above get_phys_cursor_geometry call set w->phys_cursor_width
+ to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
+ if (cursor_type == BAR_CURSOR)
+ {
+ if (cursor_width < 1)
+ cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
+ w->phys_cursor_width = cursor_width;
+ }
+ /* If we have an HBAR, "cursor_width" MAY specify height. */
+ else if (cursor_type == HBAR_CURSOR)
+ {
+ cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
+ fy += h - cursor_height;
+ h = cursor_height;
+ }
+
r.origin.x = fx, r.origin.y = fy;
r.size.height = h;
r.size.width = w->phys_cursor_width;
/* FIXME: if we overwrite the internal border area, it does not get erased;
fix by truncating cursor, but better would be to erase properly */
overspill = r.origin.x + r.size.width -
- WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w)
+ WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w)
- WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f));
if (overspill > 0)
r.size.width -= overspill;
[FRAME_CURSOR_COLOR (f) set];
break;
case HBAR_CURSOR:
- s = r;
- s.origin.y += lrint (0.75 * s.size.height);
- s.size.height = lrint (s.size.height * 0.25);
- NSRectFill (s);
+ NSRectFill (r);
break;
case BAR_CURSOR:
s = r;
- s.size.width = min (cursor_width, 2); //FIXME(see above)
-
/* If the character under cursor is R2L, draw the bar cursor
on the right of its glyph, rather than on the left. */
cursor_glyph = get_phys_cursor_glyph (w);
NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
NS_FACE_FOREGROUND (s->face) = tmp;
}
-
+
ns_tmp_font->font.driver->draw
(s, 0, s->nchars, s->x, s->y,
(ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
else
ns_maybe_dumpglyphs_background
(s, s->first_glyph->type == COMPOSITE_GLYPH);
- /* ... */
+ /* ... */
/* Not yet implemented. */
- /* ... */
+ /* ... */
ns_unfocus (s->f);
break;
strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
terminal->name[SBYTES (display_name)] = 0;
- UNBLOCK_INPUT;
+ UNBLOCK_INPUT;
if (!inhibit_x_resources)
{
stringForKey: @"AppleHighlightColor"];
if (ns_selection_color == nil)
ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
-
+
{
NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
keyEquivalent: @"q"
atIndex: 9];
- item = [mainMenu insertItemWithTitle: ns_app_name
+ item = [mainMenu insertItemWithTitle: ns_app_name
action: @selector (menuDown:)
keyEquivalent: @""
atIndex: 0];
void
ns_term_shutdown (int sig)
{
+ [[NSUserDefaults standardUserDefaults] synchronize];
+
/* code not reached in emacs.c after this is called by shut_down_emacs: */
if (STRINGP (Vauto_save_list_file_name))
unlink (SDATA (Vauto_save_list_file_name));
-appShouldTerminate
Cancel -> Nothing else
Accept ->
-
+
-terminate
KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
ns_term_shutdown()
- (void) terminate: (id)sender
{
struct frame *emacsframe = SELECTED_FRAME ();
-
+
if (!emacs_event)
return;
-
+
emacs_event->kind = NS_NONKEY_EVENT;
emacs_event->code = KEY_NS_POWER_OFF;
emacs_event->arg = Qt; /* mark as non-key event */
}
- (void)applicationDidBecomeActive: (NSNotification *)notification
{
+ NSTRACE (applicationDidBecomeActive);
+
//ns_app_active=YES;
+
+ ns_update_auto_hide_menu_bar ();
+ // No constrining takes place when the application is not active.
+ ns_constrain_all_frames ();
}
- (void)applicationDidResignActive: (NSNotification *)notification
{
code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
/* (Carbon way: [theEvent keyCode]) */
-
+
/* is it a "function key"? */
fnKeysym = ns_convert_key (code);
if (fnKeysym)
[self allocateGState];
+ [NSApp registerServicesMenuSendTypes: ns_send_types
+ returnTypes: ns_return_types];
+
ns_window_num++;
return self;
}
/*
drawRect: may be called (at least in OS X 10.5) for invisible
- views as well for some reason. Thus, do not infer visibility
+ views as well for some reason. Thus, do not infer visibility
here.
emacsframe->async_visible = 1;
}
-- validRequestorForSendType: (NSString *)typeSent
- returnType: (NSString *)typeReturned
+- (id) validRequestorForSendType: (NSString *)typeSent
+ returnType: (NSString *)typeReturned
{
NSTRACE (validRequestorForSendType);
- if ([ns_send_types indexOfObjectIdenticalTo: typeSent] != NSNotFound &&
- [ns_return_types indexOfObjectIdenticalTo: typeSent] != NSNotFound)
- return self;
+ if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
+ && (typeReturned == nil
+ || [ns_return_types indexOfObject: typeSent] != NSNotFound))
+ {
+ if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING)))
+ return self;
+ }
return [super validRequestorForSendType: typeSent
returnType: typeReturned];
- (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types
{
- /* supposed to write for as many of types as we are able */
- return NO;
+ NSArray *typesDeclared;
+ Lisp_Object val;
+
+ /* We only support NSStringPboardType */
+ if ([types containsObject:NSStringPboardType] == NO) {
+ return NO;
+ }
+
+ val = ns_get_local_selection (QPRIMARY, QUTF8_STRING);
+ if (CONSP (val) && SYMBOLP (XCAR (val)))
+ {
+ val = XCDR (val);
+ if (CONSP (val) && NILP (XCDR (val)))
+ val = XCAR (val);
+ }
+ if (! STRINGP (val))
+ return NO;
+
+ typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
+ [pb declareTypes:typesDeclared owner:nil];
+ ns_string_to_pasteboard (pb, val);
+ return YES;
}
/* When making the frame visible for the first time, we want to
constrain. Other times not. */
struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
- if (f->output_data.ns->dont_constrain)
+ NSTRACE (constrainFrameRect);
+
+ if (f->output_data.ns->dont_constrain
+ || ns_menu_bar_should_be_hidden ())
return frameRect;
f->output_data.ns->dont_constrain = 1;
DEFSYM (Qsuper, "super");
DEFSYM (Qcontrol, "control");
DEFSYM (Qnone, "none");
+ DEFSYM (QUTF8_STRING, "UTF8_STRING");
+
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
+ DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
+ doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
+Only works on OSX 10.6 or later. */);
+ ns_auto_hide_menu_bar = Qnil;
+
/* TODO: move to common code */
DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
doc: /* If not nil, Emacs uses toolkit scroll bars. */);
/* Tell emacs about this window system. */
Fprovide (intern ("ns"), Qnil);
}
-
-