Строка заголовка NSWindow недоступна для перетаскивания в ее правой половине

#objective-c #cocoa #macos #nswindow

#objective-c #cocoa #macos #nswindow

Вопрос:

У меня есть экземпляр NSWindow, размер которого я изменяю программно (с помощью setFrame). При ее создании размер по умолчанию составлял 50×50. Затем я вызываю setFrame, чтобы изменить ее размер до 350×450: все в порядке, я могу перетаскивать свое окно сколько захочу. Затем, позже в программе, я изменяю ее размер до 1024х768. На данный момент единственная часть строки заголовка, которую я могу перетащить, — это первые 350 пикселей: левая часть. Ничего не произойдет, если я перетащу правую часть. Как будто строка заголовка все еще считает, что окно имеет прежний размер.

Обновлено (добавлен код, который задает фрейм):

 void CGLWindowMac::_setSize(int width, int height)
    {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSRect sFrame;

        sFrame = [NSWindow contentRectForFrameRect:[mObjcImp frame] styleMask:[mObjcImp styleMask]];

        sFrame.origin.y  = sFrame.size.height;
        sFrame.origin.y -= height;
        sFrame.size.height = height;
        sFrame.size.width = width;
        sFrame = [NSWindow frameRectForContentRect:sFrame
                                                    styleMask:[mObjcImp styleMask]];

        NSLog(@"Frame Before setsize: cur Size(%f, %f) ", [mObjcImp frame].size.width, [mObjcImp frame].size.height);

        [mObjcImp setFrame:sFrame display:YES animate:NO];

        NSLog(@"Frame After setsize: cur Size(%f, %f) new val(%d, %d)", [mObjcImp frame].size.width, [mObjcImp frame].size.height, width, height);

        // Tell the application that the window size has change.
        onSize(width, height);

        [pool release];
    }
  

И вот результат:

 2011-05-04 08:50:47.313 ClientProMac[2461:a0f] Frame Before setsize: cur Size(50.000000, 72.000000) 
2011-05-04 08:50:47.340 ClientProMac[2461:a0f] Frame After setsize: cur Size(350.000000, 472.000000) new val(350, 450)
2011-05-04 08:50:49.148 ClientProMac[2461:7003] Frame Before setsize: cur Size(350.000000, 472.000000) 
2011-05-04 08:50:49.160 ClientProMac[2461:7003] Frame After setsize: cur Size(1024.000000, 790.000000) new val(1024, 768)
  

Странно то, что если я затем изменю размер окна, перетащив его угол, полная строка заголовка снова станет перетаскиваемой: ошибка исчезнет.

Кто-нибудь видел такое поведение раньше? Что вызывает это и как я могу это исправить.

Спасибо.

Комментарии:

1. Вы должны включить код, который изменяет размер окна и откуда оно вызывается. Возможно, размер окна изменяется в месте, которое вызывает эту ошибку.

2. Джош: Размер экрана, похоже, на это не влияет. У меня была ошибка с двойным дисплеем (оба с разрешением 1280×1024) и с одним дисплеем (1280×1024 и 1024×768).

3. Я согласен с jslap, когда вызывается ваш метод «_setSize»? Скорее всего, вы выполняете изменение размера в то время, когда Windows не может быть безопасно изменена. В опубликованном вами коде нет ничего плохого, поэтому это должно зависеть от того, что произойдет до / после этого.

4. Зачем вы создаете свой собственный пул автоматического выпуска? В этом нет ничего плохого, но это предполагает, что вы находитесь в фоновом потоке или что-то в этом роде? NSWindow вряд ли будет потокобезопасным.

5. ДА. Я делал это в другом потоке. Я думал, что NSWindows потокобезопасны. Я только что сделал это в основном потоке, и она исчезла. @Abhi: Хотите написать ответ, чтобы я мог пометить его как отвеченный?

Ответ №1:

NSWindow (и большинство операций GUI в cocoa) не являются потокобезопасными. Убедитесь, что вы изменяете размер окна в главном потоке.

Например:

 NSRect frame = NSMakeRect(42, 42, 420, 420);
dispatch_sync(dispatch_get_main_queue(), ^{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [window setFrame:frame];
    [pool release];
});
  

Если вам нужна обратная совместимость и вы не хотите использовать GCD, вы можете использовать -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].