M-x all-things-emacs

Maximize on Startup, Part 2

February 22nd, 2007 by Ryan McGeary · 144 Comments

In part 1 of the series, we discussed two ways to resize the emacs frame on startup. Here, we will use the display-pixel-width and display-pixel-height functions to automatically determine the proper size of the emacs frame.

Option 3 (the package)

As I tried to come up with a generic way to maximize the emacs frame on startup, the more the elisp moved out of my .emacs and into its own package. Soon enough, maxframe.el was born. First, I’ll describe how to install the package. Then I’ll try to describe how it works. Finally, I’ll discuss some of the caveats and gotchas.

Installation

  1. Download the full package. You can obtain the latest version (on github) or the version referenced in this article.
  2. Put maxframe.el in your load-path.
  1. Add the following to your .emacs:
(require 'maxframe)
(add-hook 'window-setup-hook 'maximize-frame t)

Maximizing the frame in the window-setup-hook helps prevent font size and window customizations from affecting the size of the newly sized frame. There are a couple optional customization variables, but we’ll explain those soon. Upon startup, emacs will resize itself to fit your display’s full resolution. Voilà.

How it works

Let’s walk through the package and explain what’s going on. Line numbers match up with the version of maxframe.el tagged for this article.

Customization variables
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(defgroup maxframe nil "Handle maximizing frames.")
 
(defcustom mf-display-padding-width 0
  "*Any extra display padding that you want to account for while
determining the maximize number of columns to fit on a display"
  :type 'integer
  :group 'maxframe)
 
;; The default accounts for a Mac OS X display with a menubar 
;; height of 22 pixels, a titlebar of 23 pixels, and no dock.
(defcustom mf-display-padding-height (+ 22 23)
  "*Any extra display padding that you want to account for while
determining the maximize number of rows to fit on a display"
  :type 'integer
  :group 'maxframe)

First, we define a new customization group and add two new variables to allow for extra display padding if desired. The defaults were designed for Mac OS X, with the menu-bar and title-bar, but without the dock visible. I hide my toolbar, but that doesn’t seem to affect the calculations anyway. Run M-x customize-group RET maxframe RET or add the appropriate setq calls in your .emacs to fit to your liking.

Windows specific functions
62
63
64
65
66
67
68
69
70
(defun w32-maximize-frame ()
  "Maximize the current frame (windows only)"
  (interactive)
  (w32-send-sys-command 61488))
 
(defun w32-restore-frame ()
  "Restore a minimized/maximized frame (windows only)"
  (interactive)
  (w32-send-sys-command 61728))

These were taken nearly verbatim from the GNU Emacs FAQ. They directly access the Windows system commands to maximize/restore the containing window. Later we’ll see that when Windows is detected, w32-maximize-frame is used to short-circuit the other maximize frame functions.

Columns and rows
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(defun mf-max-columns (width)
  "Calculates the maximum number of columns that can fit in
pixels specified by WIDTH."
  (let ((scroll-bar (or (frame-parameter nil 'scroll-bar-width) 0))
        (left-fringe (or left-fringe-width (nth 0 (window-fringes)) 0))
        (right-fringe (or right-fringe-width (nth 1 (window-fringes)) 0)))
    (/ (- width scroll-bar left-fringe right-fringe
          mf-display-padding-width)
       (frame-char-width))))
 
(defun mf-max-rows (height)
  "Calculates the maximum number of rows that can fit in pixels
specified by HEIGHT."
  (/ (- height
        mf-display-padding-height)
     (frame-char-height)))

These two functions take pixel dimensions and calculate the max number of characters that can fit in those dimensions. Both functions account for the padding values we talked about above, but the columns are also affected by the scroll-bar and fringes (lines 75-77). The widths of these values are subtracted from the base pixel width before dividing by the character pixel width. The mf-max-rows function is a bit simpler, because less window decoration affects it.

Resize frame using pixels
89
90
91
(defun mf-set-frame-pixel-size (frame width height)
  "Sets size of FRAME to WIDTH by HEIGHT, measured in pixels."
  (set-frame-size frame (mf-max-columns width) (mf-max-rows height)))

This function was designed to mimic the built-in set-frame-size function but to instead accept pixel dimensions instead of column and row arguments. It merely calls set-frame-size given the return values from the mf-max-columns and mf-max-rows functions.

X-Window/Mac specific function
93
94
95
96
97
98
99
(defun x-maximize-frame ()
  "Maximize the current frame (x or mac only)"
  (interactive)
  (mf-set-frame-pixel-size (selected-frame)
                           (display-pixel-width)
                           (display-pixel-height))
  (set-frame-position (selected-frame) 0 0))

This tries to mimic the behavior of w32-maximize-frame found on line 62 but for x-window and mac systems. It uses display-pixel-width and display-pixel-height to resize the current frame to fit the display and moves the frame to the top left corner of the display which is situated at (0,0).

Maximize frame
101
102
103
104
105
106
(defun maximize-frame ()
  "Maximizes the frame to fit the display if under a windowing
system."
  (interactive)
  (cond ((eq window-system 'w32) (w32-maximize-frame))
        ((memq window-system '(x mac)) (x-maximize-frame))))

This is where the butter meets the bread. If under a Windows windowing system, w32-maximize-frame is called (line 105) and Windows handles the rest . If under an X-Window or Mac windowing system, we call our custom x-maximize-frame function (line 106) to to sort out the rest.

The rest
108
109
110
(defalias 'mf 'maximize-frame)
 
(provide 'maxframe)

Line 108 defines a new alias that makes it quicker to manually maximize your frame (i.e. M-x mf instead of M-x maximize-frame). Like any good package, on line 110, we announce our new maxframe feature to emacs with the provide function. This allows an associated (require 'maxframe) call to load the functionality into emacs.

Gripes

One issue I ran into during this exercise is that emacs does not recognize when the display’s resolution is changed. This is a problem because I would like to be able to re-maximize the frame (M-x mf) after I connect my laptop to an external monitor. Unfortunately, display-pixel-width and display-pixel-height yield the display resolution values from when emacs was started instead of the current display values. Perhaps there’s a way to have emacs re-sniff these values, but I don’t know how. If anyone has suggestions, please post a comment.
[Update: This was fixed in the release version of Emacs 22.]

This was designed for Emacs 22. The fringe related functions and variables probably won’t work on Emacs 21. The Windows specific functions should still work on Emacs 21 though.

While I’m glad I was able to achieve this kind of functionality with elisp, I am disapointed it required the extra work. Having to manually account for scroll-bars, fringes, menu-bars, title-bars, etc is a little crazy in my opinion. I’d like to see more of this behavior accounted for in the core. I’d prefer if there existed a function (e.g. set-frame-pixel-size) that correctly sized the frame to the proper pixel dimensions.

Tags: elisp · osx · tips · windows · x

144 responses so far ↓

  • 1 James Radford Web Developer // Jun 6, 2010 at 9:16 am

    Thanks for the post, really useful!

  • 2 Michael Brand // Jun 16, 2010 at 4:39 pm

    Hi rohan nicholls,
    Are you looking for something like the function count-lines-page which tells the number of lines the current buffer has? If yes it should be easy to include a return of the total.

  • 3 forex // Aug 29, 2010 at 12:26 am

    Thanks for your add-on. Now I can maximize easily in carbon emacs-os x.

  • 4 WP-Syntax – Code HighLighting ?????? for Wordpress « Kebot // Sep 26, 2010 at 8:42 am

    [...] plugin was originally written for use with EmacsBlog. To see it in action, scroll through this particular post or visit [...]

  • 5 Michael V. Antosha // Jan 26, 2011 at 12:02 pm

    Thanks, it “just works”!

  • 6 Azubuike // Jun 30, 2012 at 5:52 pm

    It’s a nice plugin worth trying out.

    I will give it a try and see how it works.
    Thanks

  • 7 Yesudeep Mangalapilly // Jul 30, 2012 at 7:48 pm

    Hey there,

    Thank you for this module. Loved it.

    However, when I try to use it on OS X Lion
    with Emacs 24, it seems to “hide” the first line
    of every buffer. Are there any workarounds to this?

    Cheers,
    Yesudeep.

  • 8 Ryan McGeary // Jul 31, 2012 at 7:14 pm

    Yesudeep,

    There’s little reason to use this library on OS X and Emacs 24 anymore, but is your issue the same as what is described here?
    https://github.com/rmm5t/maxframe.el/issues/2

    If so, feel free to chime in and participate, but also read my reply. I suggest using ns-toggle-fullscreen on Emacs 24 on OS X instead.

  • 9 Inforscience // Aug 7, 2012 at 11:08 pm

    [...] plugin was originally written for use with EmacsBlog. To see it in action, scroll through this particular post or visit the [...]