Tuesday, May 15, 2007
Tuesday, October 03, 2006
Keyboard handling patch
Mac Vims Carbon keyboard handling code doesn't apply modifiers (like shift) to special keys like the arrow keys. I wrote a patch to take care of this.
Of couse, this patch causes a few regressions (which I'm trying to fix).
I have to test the following keys with each version of the patch to make sure the regressions stay fixed:
C-V S-Left should insert "<s-left>" in insert mode.Done by original patch.Mappings likeFix: Don't send CTRL modifier for keys with ASCII code < 32
map <c-e> <end>
map <c-a> <home>
should work (insert mode and normal mode) (regression found by Kyle Wheeler).C-F and C-B should work in normal mode (regression found by Bram Molenaar).Seems to be fixed by the patch that fixed the previous problem as well.Shift-Tab should give previous match in command line completion (found by Bram Molenaar as well). simplify_key() seems to mess up the shift-tab keys.Shift-Tab is a special key and has to be send as such.- Shift-Space has to work (the code that removes shift from chars like (, *, + etc. removes it from space as well).
Unicode characters (ä etc.) should work (they are broken because of the Shift-Tab patch at the moment).- :map ç j doesn't work
Notes: Keyboard layout files; this seems to be what I'm looking for
The latest version of the patch can be found here.
Sunday, August 27, 2006
Green Circle of Confusion
According to Apple's HIG, it toggles between a user state and a standard state -- it doesn't maximize your window -- and the HIG explicitely advice against maximizing your window. However, this is exactly what Carbon's standard window handler does. If you want to change it, you are advised to write a listener to the kEventWindowZoom event.
However, implementing the kEventWindowZoom yourself is a bad idea, because no one really knows what this button should do. Try Option-Clicking the zoom box in several apps and see what happens for instance. Finder, for example, does weird things. But, hey, we're used to that, aren't we?
Fortunately, you can get around writing your own kEventWindowZoom handler most of the time. You only need to implement an kEventWindowGetIdealSize handler and return the standard state size of your window. The standard window handler does the rest. Option-Clicking moves the window into the upper left window, as it turns out. Here's how Vim responds to that event:
static OSStatus onWindow(EventHandlerCallRef handler,
EventRef event, void *data)
{
Point p;
UInt32 attributes;
GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL,
sizeof(UInt32), NULL, &attributes);
switch(GetEventKind(event))
{
case kEventWindowGetIdealSize:
/* ideal width is current */
p.h = Columns * gui.char_width + gui_get_base_width();
/* ideal height is as high as we can get */
p.v = 15 * 1024;
SetEventParameter(event, kEventParamDimensions, typeQDPoint,
sizeof(p), &p);
break;
}
return noErr;
}
Thursday, August 24, 2006
Notes on porting Vim Mac to Carbon Events
Before porting to Carbon events, gui_mac.c is about 6500 lines (with gui tab pages).
Plan: Replace WaintForNextEvent() with RunApplicationEventLoop() (and use CreateNewWindow() instead of NewCWindow() in gui_mch_init()), use standard event handler. Check what codes needs to be changed. We need callbacks for
- Keyboard events (seems to be already in place)
- Mouse events
- Menu events
- Control events
Stuff that's influenced by a change to Carbon Events and the standard event handler:
- proxy icon handling is done automatically (as soon as proxy icons are supported)
- toolbar config stuff is done automatically (as soon as there's a toolbar)
- window movement, app activation, menu handling...
- window resizing becomes life (can prolly be prevented if this turns out to be annoying, though)
- drawing is automatically double buffered (it's prolly buffered atm as well, so this is no real change) -- think about drawing code
- gui_mch_wait_for_chars() (or whatever it's called) has to work with the event stuff -- see gui_win48 how they do it
- Control handling code should get easier (at least once controls are used in the osx way)
Important functions to convert:
- gui_mch_wait_for_chars() (calls WaitNextEvent())
- gui_mac_handle_event()
Stuff to take care off:
- redraw only up to N (˜ 25) times per second (measure fps? prolly overkill)
- scrolling must not be allowed under certain cirumstances (allow_scrollbar)
- Standard App Handler is called automatically by RunApplicationEventLoop(), Standard Window Handler has to be specified with the kWindowStandardHandlerAttribute (in CreateNewWindow() or ChangeWindowAttributes(), preferably the first)
- Carbon event docu (reference)
- Macintosh C Carbon
- Writing your own event loop (perhaps neccesary for wtime)
- QA1016 (about the same thing, perhaps a bit dated?)
- MenuSelect
Gui Tabline
Vim7 added support for tabs. However, the mac version doesn't have gui tabs.
There are several ways to implement gui tabs in mac vim:
- Segmented view
Pros:
- Tabs like you expect them
- Doesn't need much space
Cons:
- Needs OS X 10.3
- needs compositing enabled
- seems that this needs a standard event handler on the main window, which makes resizing and maximizing choke. Without the standard handler, clicking the tab bar doesn't work...perhaps this can be fixed without a standard handler?
There are two ways this can be implemented:
- Put the segmented view in the root view of the window. This has the advantage that it works with less effort and gives more vertical room for vim (but makes moving the window with the mouse somewhat harder). Another problem is that no title bar text is available, this is annoying if you use Expose for example. Additionally, it looks really ugly.
- Put the segmented view in the content view of the window. This requires more changes (vim's text window has to be converted to a view, which are only supported from 10.2 on), but it's what you'd normally expect. Plus, if the text area is a view, this gives us the ability to add a toolbar as well; it should also improve drawing performance and is recommended by apple as the "future".
The segmented view should change its size when the window is resized, if there are a lot of tabs, they should be made smaller so that they are all visible. Alternatively, left/right arrows can be added after a certain minimal tab size (see this page for an example).
It looks like this:
todo: make tabs clickable ( gui_mac_doMouseDownEvent ?),
make tabs smaller if they don't fit otherwise, resize max toolbar size when window is resized- Drawer
Pros:
- works with older mac os x versions (10.2)
- Doesn't need vertical screen space
- has room for a lot of tabs. the drawer could display tabs hierarchically, this way you could have whole trees open.
- other gui stuff could be added to the drawer
Cons:
- unexpected
- needs some horizontal screen space
- according to this, data browser doesn't work with compositing on 10.2, but drawers need compositing. so this might not really work on 10.2 :-(
It looks like this:
-
todo:
crashes when -p *.h is used (stl=1, close all but the first tab, open new tab) (might be fixed by now, was unable to reproduce this), crashes when doing sta=1, set lines=20, set lines=40, tabe . q, tabe .(fixed in v4), if the window size is set to a smaller than minmal
height with :set lines=10 the display looks really strange, scrollbar flashes black on tab change, context menu close is only applied after mouse move (probably some event stuff) - One window for each tab
Use a separate window for each tab. This would be very maccy, but has probably some problems because the windows can have different sizes.
- External tab lib
Use this tab control.
Pros
- Looks good, is what you'd expect
- maintained by others, and used in other apps (iterm,colloquy, adium
want to use it too)
Cons
- The lib is in cocoa, so we need a wrapper to call it from C.
- Needs views as well
Stuff to test
- :tabe äö (this killed a few of my vims)
- :tabe aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (check what happens with long file names...should be shortened somehow)
I've implemented the segmented view and the drawer variants. I like the drawer version so much that I'll keep it for now. You really get used to having 20+ tabs open, and only the drawer version supports that.
Brainstorming
Stuff that could be improved in mac vim:
- add proxies to the title bar, call SetWindowChanged (see here for details) - gui_mch_update, gui_mch_flush. Window proxies see here: AliasHandle, SetWindowProxyAlias, IsWindowPathSelectClick, WindowPathSelect (and SetWindowModified of course)
- improved atsui stuff (draw_string_QD/draw_string_ATSUI)
- (more than one window per session...)
- generate "Press Enter or enter command..." message, tab, cmd-tab: more messages are generated
trackpad scrolling is currently a bit jittery because left/right movement scrolls as well (so left/down movement jitters)donectrl-click for context menu, then click somewhere else - another popup is openeddone (not by me)- (not mac specific) when a file is selected in :e . , the :pwd part should be stripped if the file is somewhere below pwd
- pum shouldn't flicker (don't redraw too soon?)
- use carbon events
- use hiview
- Vim->About should work
- use mac os built-in spell checker :-P
- activating left scrollbar doesn't really work
- repainting whoes (scrollbar on/off; select new tab via drawer, :set cursorline etc)
- :set cursorline should move highlight and cursor at the same time, currently cursor is moved, screen is redrawn, and then the line is moved (and the screen is again redrawn)
- Fullscreen mode ;-)
- :map <d-a-c> doesn't work (<d-s-c&gk; does work, though)
- scrollbar thumb should be of the appropriate size
- font selection dialog should be modeless
- font antialiasing that works! (aquamacs is able to do it)
- resize frame should only show allowed increments (better yet: life resizing)
- start to resize the window, hit escape, move mouse -- vim explodes
- drag-n-drop from/to tab drawer (cf. proxy icons as well)
- drag-n-drop tab reordering
- antialias doesn't work with macatsui, umlauts don't work without macatsui
- convert the ugly dialog boxes to sheets, add better keyboard support to them (if they are left as dialog boxes, they should be moveable at least)
- remove "Help" item from context menu
- Use FSRefs instead of paths everywhere
other mac text editors one can look at for some inspiration ;-):
- TextWrangler
- Emacs (Aquamacs looks the most polished) ;-)
- Smultron
- TextMate
- XCode :-P