mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -191,6 +191,7 @@ enum {
|
||||
NetBeansMsgID,
|
||||
SetMarkedTextMsgID,
|
||||
ZoomMsgID,
|
||||
SetWindowPositionMsgID,
|
||||
LastMsgID // NOTE: MUST BE LAST MESSAGE IN ENUM!
|
||||
};
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ char *MessageStrings[] =
|
||||
"NetBeansMsgID",
|
||||
"SetMarkedTextMsgID",
|
||||
"ZoomMsgID",
|
||||
"SetWindowPositionMsgID",
|
||||
"END OF MESSAGE IDs" // NOTE: Must be last!
|
||||
};
|
||||
|
||||
|
||||
+18
-16
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user