Add support for :winpos

Note that window coordinates are specified in a coordinate system where
X points to the right and Y points upwards.
This commit is contained in:
Bjorn Winckler
2010-02-20 00:40:23 +01:00
parent 9e30756b1f
commit c5c236f87d
9 changed files with 128 additions and 24 deletions
+14 -6
View File
@@ -743,15 +743,23 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
- (void)windowControllerWillOpen:(MMWindowController *)windowController
{
NSPoint topLeft = NSZeroPoint;
NSWindow *topWin = [[[self topmostVimController] windowController] window];
NSWindow *cascadeFrom = [[[self topmostVimController] windowController]
window];
NSWindow *win = [windowController window];
if (!win) return;
// If there is a window belonging to a Vim process, cascade from it,
// otherwise use the autosaved window position (if any).
if (topWin) {
NSRect frame = [topWin frame];
// Heuristic to determine where to position the window:
// 1. Use the default top left position (set using :winpos in .[g]vimrc)
// 2. Cascade from an existing window
// 3. Use autosaved position
// If all of the above fail, then the window position is not changed.
if ([windowController getDefaultTopLeft:&topLeft]) {
// Make sure the window is not cascaded (note that topLeft was set in
// the above call).
cascadeFrom = nil;
} else if (cascadeFrom) {
NSRect frame = [cascadeFrom frame];
topLeft = NSMakePoint(frame.origin.x, NSMaxY(frame));
} else {
NSString *topLeftString = [[NSUserDefaults standardUserDefaults]
@@ -767,7 +775,7 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
if (!screen)
screen = [win screen];
if (topWin) {
if (cascadeFrom) {
// Do manual cascading instead of using
// -[MMWindow cascadeTopLeftFromPoint:] since it is rather
// unpredictable.
+4
View File
@@ -53,6 +53,8 @@
BOOL imState;
CFSocketRef netbeansSocket;
CFRunLoopSourceRef netbeansRunLoopSource;
int winposX;
int winposY;
}
+ (MMBackend *)sharedInstance;
@@ -64,6 +66,8 @@
- (NSConnection *)connection;
- (NSDictionary *)actionDict;
- (int)initialWindowLayout;
- (void)getWindowPositionX:(int*)x Y:(int*)y;
- (void)setWindowPositionX:(int)x Y:(int)y;
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props;
- (BOOL)checkin;
+38
View File
@@ -326,6 +326,24 @@ extern GuiFont gui_mch_retain_font(GuiFont font);
return initialWindowLayout;
}
- (void)getWindowPositionX:(int*)x Y:(int*)y
{
// NOTE: winposX and winposY are set by the SetWindowPositionMsgID message.
if (x) *x = winposX;
if (y) *y = winposY;
}
- (void)setWindowPositionX:(int)x Y:(int)y
{
// NOTE: Setting the window position has no immediate effect on the cached
// variables winposX and winposY. These are set by the frontend when the
// window actually moves (see SetWindowPositionMsgID).
ASLogDebug(@"x=%d y=%d", x, y);
int pos[2] = { x, y };
NSData *data = [NSData dataWithBytes:pos length:2*sizeof(int)];
[self queueMessage:SetWindowPositionMsgID data:data];
}
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props
{
[self queueMessage:msgid data:[props dictionaryAsData]];
@@ -440,7 +458,21 @@ extern GuiFont gui_mch_retain_font(GuiFont font);
- (BOOL)openGUIWindow
{
if (gui_win_x != -1 && gui_win_y != -1) {
// NOTE: the gui_win_* coordinates are both set to -1 if no :winpos
// command is in .[g]vimrc. (This way of detecting if :winpos has been
// used may cause problems if a second monitor is located to the left
// and underneath the main monitor as it will have negative
// coordinates. However, this seems like a minor problem that is not
// worth fixing since all GUIs work this way.)
ASLogDebug(@"default x=%d y=%d", gui_win_x, gui_win_y);
int pos[2] = { gui_win_x, gui_win_y };
NSData *data = [NSData dataWithBytes:pos length:2*sizeof(int)];
[self queueMessage:SetWindowPositionMsgID data:data];
}
[self queueMessage:OpenWindowMsgID data:nil];
return YES;
}
@@ -1952,6 +1984,12 @@ static void netbeansReadCallback(CFSocketRef s,
// regarding resizing.)
[self queueMessage:ZoomMsgID data:data];
gui_resize_shell(cols, rows);
} else if (SetWindowPositionMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
winposX = *((int*)bytes); bytes += sizeof(int);
winposY = *((int*)bytes); bytes += sizeof(int);
ASLogDebug(@"SetWindowPositionMsgID: x=%d y=%d", winposX, winposY);
} else {
ASLogWarn(@"Unknown message received (msgid=%d)", msgid);
}
+6
View File
@@ -824,6 +824,12 @@ static BOOL isUnsafeMessage(int msgid);
[windowController zoomWithRows:rows
columns:cols
state:state];
} else if (SetWindowPositionMsgID == msgid) {
const void *bytes = [data bytes];
int x = *((int*)bytes); bytes += sizeof(int);
int y = *((int*)bytes); bytes += sizeof(int);
[windowController setTopLeft:NSMakePoint(x,y)];
// IMPORTANT: When adding a new message, make sure to update
// isUnsafeMessage() if necessary!
} else {
+3
View File
@@ -38,6 +38,7 @@
int userRows;
int userCols;
NSPoint userTopLeft;
NSPoint defaultTopLeft;
}
- (id)initWithVimController:(MMVimController *)controller;
@@ -78,6 +79,8 @@
- (void)setFullscreenBackgroundColor:(NSColor *)back;
- (void)setBuffersModified:(BOOL)mod;
- (void)setTopLeft:(NSPoint)pt;
- (BOOL)getDefaultTopLeft:(NSPoint*)pt;
- (IBAction)addNewTab:(id)sender;
- (IBAction)toggleToolbar:(id)sender;
+43 -2
View File
@@ -640,6 +640,30 @@
[decoratedWindow setDocumentEdited:mod];
}
- (void)setTopLeft:(NSPoint)pt
{
if (setupDone) {
[decoratedWindow setFrameTopLeftPoint:pt];
} else {
// Window has not been "opened" yet (see openWindow:) but remember this
// value to be used when the window opens.
defaultTopLeft = pt;
}
}
- (BOOL)getDefaultTopLeft:(NSPoint*)pt
{
// A default top left point may be set in .[g]vimrc with the :winpos
// command. (If this has not been done the top left point will be the zero
// point.)
if (pt && !NSEqualPoints(defaultTopLeft, NSZeroPoint)) {
*pt = defaultTopLeft;
return YES;
}
return NO;
}
- (IBAction)addNewTab:(id)sender
{
@@ -792,14 +816,20 @@
return;
}
NSRect frame = [decoratedWindow frame];
NSPoint topLeft = { frame.origin.x, NSMaxY(frame) };
if (windowAutosaveKey) {
NSRect frame = [decoratedWindow frame];
NSPoint topLeft = { frame.origin.x, NSMaxY(frame) };
NSString *topLeftString = NSStringFromPoint(topLeft);
[[NSUserDefaults standardUserDefaults]
setObject:topLeftString forKey:windowAutosaveKey];
}
// NOTE: This method is called when the user drags the window, but not when
// the top left point changes programmatically.
int pos[2] = { (int)topLeft.x, (int)topLeft.y };
NSData *data = [NSData dataWithBytes:pos length:2*sizeof(int)];
[vimController sendMessage:SetWindowPositionMsgID data:data];
}
- (void)windowDidResize:(id)sender
@@ -978,6 +1008,17 @@
}
[decoratedWindow setFrame:newFrame display:YES];
NSPoint oldTopLeft = { frame.origin.x, NSMaxY(frame) };
NSPoint newTopLeft = { newFrame.origin.x, NSMaxY(newFrame) };
if (!NSEqualPoints(oldTopLeft, newTopLeft)) {
// NOTE: The window top left position may change due to the window
// being moved e.g. when the tabline is shown so we must tell Vim what
// the new window position is here.
int pos[2] = { (int)newTopLeft.x, (int)newTopLeft.y };
NSData *data = [NSData dataWithBytes:pos length:2*sizeof(int)];
[vimController sendMessage:SetWindowPositionMsgID data:data];
}
}
- (NSSize)constrainContentSizeToScreenSize:(NSSize)contentSize
+1
View File
@@ -191,6 +191,7 @@ enum {
NetBeansMsgID,
SetMarkedTextMsgID,
ZoomMsgID,
SetWindowPositionMsgID,
LastMsgID // NOTE: MUST BE LAST MESSAGE IN ENUM!
};
+1
View File
@@ -94,6 +94,7 @@ char *MessageStrings[] =
"NetBeansMsgID",
"SetMarkedTextMsgID",
"ZoomMsgID",
"SetWindowPositionMsgID",
"END OF MESSAGE IDs" // NOTE: Must be last!
};
+18 -16
View File
@@ -1654,17 +1654,6 @@ gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
}
/*
* Get the position of the top left corner of the window.
*/
int
gui_mch_get_winpos(int *x, int *y)
{
*x = *y = 0;
return OK;
}
/*
* Return OK if the key with the termcap name "name" is supported.
*/
@@ -1714,17 +1703,30 @@ gui_mch_set_shellsize(
}
void
gui_mch_set_text_area_pos(int x, int y, int w, int h)
{
}
/*
* Set the position of the top left corner of the window to the given
* coordinates.
*/
void
gui_mch_set_winpos(int x, int y)
{
[[MMBackend sharedInstance] setWindowPositionX:x Y:y];
}
/*
* Get the position of the top left corner of the window.
*/
int
gui_mch_get_winpos(int *x, int *y)
{
[[MMBackend sharedInstance] getWindowPositionX:x Y:y];
return OK;
}
void
gui_mch_set_text_area_pos(int x, int y, int w, int h)
{
}