Skip to content

Instantly share code, notes, and snippets.

@mstepniowski
Created July 20, 2011 22:19
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mstepniowski/1096074 to your computer and use it in GitHub Desktop.
Save mstepniowski/1096074 to your computer and use it in GitHub Desktop.
Add Lion-based fullscreen mode to Emacs 24
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index 447d7fd..27bba4a 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -929,6 +929,11 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(add-to-list 'window-system-initialization-alist '(ns . ns-initialize-window-system))
+(declare-function ns-toggle-fullscreen-internal "nsfns.m" ())
+(defun ns-toggle-fullscreen ()
+ (interactive)
+ (ns-toggle-fullscreen-internal))
+
(provide 'ns-win)
;;; ns-win.el ends here
diff --git a/src/nsfns.m b/src/nsfns.m
index 0452086..61d4d65 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2573,6 +2573,34 @@ Value is t if tooltip was open, nil otherwise. */)
#endif
+DEFUN ("ns-toggle-fullscreen-internal", Fns_toggle_fullscreen_internal, Sns_toggle_fullscreen_internal,
+ 0, 0, 0,
+ doc: /* Toggle fulscreen mode */)
+ ()
+{
+ struct frame *f = SELECTED_FRAME();
+ EmacsWindow *window = ns_get_window(f);
+
+ EmacsWindow *new_window = [window toggleFullscreen];
+ FRAME_NS_WINDOW(f) = new_window;
+
+ NSRect r = [new_window contentRectForFrameRect:[new_window frame]];
+ int cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS(f, r.size.width);
+ int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES(f, r.size.height);
+
+ change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
+ FRAME_PIXEL_WIDTH (f) = (int)r.size.width;
+ FRAME_PIXEL_HEIGHT (f) = (int)r.size.height;
+
+ f->border_width = [new_window frame].size.width - r.size.width;
+ FRAME_NS_TITLEBAR_HEIGHT (f) =
+ [new_window frame].size.height - r.size.height;
+
+ [[new_window delegate] windowDidMove:nil];
+
+ return Qnil;
+}
+
/* ==========================================================================
@@ -2658,6 +2686,8 @@ be used as the image of the icon representing the frame. */);
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
+ defsubr (&Sns_toggle_fullscreen_internal);
+
/* used only in fontset.c */
check_window_system_func = check_ns;
diff --git a/src/nsterm.h b/src/nsterm.h
index f419391..cc3b829 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -116,8 +116,25 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
{
NSPoint grabOffset;
}
+
+-(EmacsWindow *)toggleFullscreen;
+
+@end
+
+/* 10.5 or below is not supported [NSWindow setStyleMask:], so require content swap hack */
+@interface EmacsFullWindow : EmacsWindow {
+ EmacsWindow *normalWindow;
+}
+
+-(id)initWithNormalWindow:(EmacsWindow *)window;
+-(EmacsWindow *)getNormalWindow;
+
@end
+// dummy for 10.5-
+#define NSApplicationPresentationDefault 0
+#define NSApplicationPresentationAutoHideDock (1 << 0)
+#define NSApplicationPresentationAutoHideMenuBar (1 << 2)
/* ==========================================================================
diff --git a/src/nsterm.m b/src/nsterm.m
index 546247a..b59fa06 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -797,6 +797,13 @@ ns_focus (struct frame *f, NSRect *r, int n)
/*debug_lock--; */
}
+ if (view) {
+ EmacsFullWindow *win = [view window];
+ if ([win isKindOfClass:[EmacsFullWindow class]]) {
+ [[win getNormalWindow] orderOut:nil];
+ }
+ }
+
if (view)
#ifdef NS_IMPL_GNUSTEP
r ? [view lockFocusInRect: u] : [view lockFocus];
@@ -1262,8 +1269,14 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
compute_fringe_widths (f, 0);
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+ if ([window isKindOfClass:[EmacsFullWindow class]]) {
+ pixelwidth = [[window screen] frame].size.width;
+ pixelheight = [[window screen] frame].size.height;
+ }
+ else {
+ pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
+ pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+ }
/* If we have a toolbar, take its height into account. */
if (tb)
@@ -1312,7 +1325,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
-/* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
+ /* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
mark_window_cursors_off (XWINDOW (f->root_window));
cancel_mouse_face (f);
@@ -5861,6 +5874,65 @@ ns_term_shutdown (int sig)
}
+-(NSWindow *)toggleFullscreen {
+ // OS X Lion
+ if ([super respondsToSelector: @selector(toggleFullScreen:)]) {
+ [super toggleFullScreen:self];
+ return self;
+ }
+
+ BOOL isFullscreen = [[self className] isEqualToString:@"EmacsFullWindow"];
+ NSWindow *win;
+
+ if (isFullscreen) {
+ EmacsFullWindow *f = (EmacsFullWindow *)self;
+ EmacsWindow *w = [f getNormalWindow];
+
+ [w setContentView:[f contentView]];
+ [w makeKeyAndOrderFront:nil];
+
+ [f close];
+
+ win = w;
+
+ if ([[self screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) {
+ if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+ else {
+ [NSMenu setMenuBarVisible:YES];
+ }
+ }
+ }
+ else {
+ [self deminiaturize:nil];
+
+ if ([[self screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) {
+ if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
+ [NSApp setPresentationOptions:NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar];
+ }
+ else {
+ [NSMenu setMenuBarVisible:NO];
+ }
+ }
+
+ [self orderOut:nil];
+
+ EmacsFullWindow *f = [[EmacsFullWindow alloc] initWithNormalWindow:self];
+ EmacsView *view = (EmacsView *)[self delegate];
+ [f setDelegate:view];
+ [f makeFirstResponder:view];
+ [f setContentView:[self contentView]];
+ [f setContentSize:[[self screen] frame].size];
+ [f setTitle:[self title]];
+ [f makeKeyAndOrderFront:nil];
+
+ win = f;
+ }
+
+ return win;
+}
+
/* called only on resize clicks by special case in EmacsApp-sendEvent */
- (void)mouseDown: (NSEvent *)theEvent
{
@@ -5916,6 +5988,32 @@ ns_term_shutdown (int sig)
@end /* EmacsWindow */
+@implementation EmacsFullWindow
+
+-(BOOL)canBecomeKeyWindow {
+ return YES;
+}
+
+-(id)initWithNormalWindow:(EmacsWindow *)window {
+ self = [super initWithContentRect:[window contentRectForFrameRect:[[window screen] frame]]
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ if (self) {
+ normalWindow = window;
+ [self setAcceptsMouseMovedEvents: YES];
+ [self useOptimizedDrawing: YES];
+ }
+
+ return self;
+}
+
+-(EmacsWindow *)getNormalWindow {
+ return normalWindow;
+}
+
+@end /* EmacsFullWindow */
+
/* ==========================================================================
@mitchellh
Copy link

Found this via Google! Does this work? :) What is the status of this patch?

@mstepniowski
Copy link
Author

It partially works (tested with an Emacs version from homebrew) but unfortunately there are still some bugs. I will work on the patch during the weekend.

@leifwalsh
Copy link

this doesn't work at all with a version built from bzr, there are no errors, it just does nothing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment