Автосохранение NSWindow - позиция не сохраняется на втором мониторе

В Yosemite (и, возможно, ранее) механизм автосохранения оконных рамок не учитывает автоматическое позиционирование окон, которые были перемещены с основного дисплея на второй монитор, или любую позицию, которая перекрывает второй монитор.

Вместо этого при следующем создании окно автоматически размещается в предыдущем местоположении (если в параметрах по умолчанию было записано действительное положение) или в положение по умолчанию для окна, или, в случае перекрывающихся окон, в положение, при котором окно полностью помещается в исходное положение. главный экран.

Это происходит независимо от того, установлено ли свойство имени автосохранения для окна в Интерфейсном Разработчике или через NSWindowController. например

-(void)windowDidLoad
{
    [super windowDidLoad];
    [self setShouldCascadeWindows:NO];
    [self setWindowFrameAutosaveName:@"MyWindowAutoSaveName"];
}

Кто-нибудь знает обходной путь?


person Womble    schedule 11.05.2015    source источник


Ответы (1)


Я никогда не мог заставить автосохранение восстановиться на втором мониторе. Никакая порка не заставит его работать. Он будет восстановлен на первом мониторе в той же позиции xy, что и окно на втором мониторе. Чтобы решить эту проблему, я отказался от использования API автосохранения и сделал свой собственный.

Когда вызывается метод окна windowWillClose:, сначала сохраните BOOL, который указывает, было ли окно полноэкранным. Затем, если окно не было увеличено (подробнее об этом чуть позже), используйте NSStringFromRect и сохраните прямоугольник кадра окна.

-(void)windowWillClose:(NSNotification *)notification
{
  NSString  *mainWindowFrameString;

  [_defaults setObject:[NSNumber numberWithBool:[_flimFlamViewController windowIsFullScreen]] forKey:QUITTING_ZOOM_STATE];

  if ([_flimFlamViewController windowIsFullScreen] == NO) {
    mainWindowFrameString = NSStringFromRect([_ourWindow frame]);
    [_defaults setObject:mainWindowFrameString forKey:MAIN_WINDOW_FRAME];
    }

  [_defaults synchronize];

}

И наоборот, когда окно создано (возможно, в awakeFromNib:), загрузите строку из NSUserDefaults и используйте NSRectFromString для получения границ. Проверьте размеры фреймов на ноль, чтобы увидеть, запущено ли приложение в первый раз. Если фрейм не состоит из всех нулей, установите фрейм окна в этот CGRect.

  mainWindowFrameString = [_defaults objectForKey:MAIN_WINDOW_FRAME];       // get the last saved window frame values
  mainWindowFrame = NSRectFromString(mainWindowFrameString);                // convert it to a CGRect

  if ((mainWindowFrame.size.width != 0) && (mainWindowFrame.size.height != 0)) {
    [_ourWindow setFrame:mainWindowFrame display:YES];
    }
  else {
    [_ourWindow center];
    }

Чтобы обработать случай полноэкранного масштабирования окна, когда окно было закрыто, сначала сохраните положение кадра, прежде чем оно станет полноэкранным - вы будете использовать это позже, когда окно снова откроется, чтобы поместить окно на соответствующий монитор.

-(void)windowWillEnterFullScreen:(NSNotification *)notification
{
  NSString  *mainWindowFrameString;

  // save the frame's coordinates before going full screen

  mainWindowFrameString = NSStringFromRect([_ourWindow frame]);
  [_defaults setObject:mainWindowFrameString forKey:MAIN_WINDOW_FRAME];
}

Затем в viewWillAppear: определите, нужно ли вам масштабировать окно (окно в этот момент уже размещено на соответствующем мониторе). toggleFullScreen: сделает окно полноэкранным.

  lastZoomStateDefault = [_defaults objectForKey:QUITTING_ZOOM_STATE];
  _windowIsFullScreen = [lastZoomStateDefault boolValue];

  if (_windowIsFullScreen == YES) {
    [_window toggleFullScreen:nil];
    }
person Chris Walken    schedule 02.05.2016