From 42c8c59a7be5e1906de09b6a007b868c897ab9e1 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 24 Jul 2009 12:10:21 +0200 Subject: Prematurely creating a dialog as a sheet causes problems Prematurely creating a dialog as a sheet and then calling exec() on it will show a window w/o decorations. The problem is that first telling a window to be a sheet, and then tell it to exec, is unambigious. Because doing the latter implies application modality (when modality is not set), which again implies not using a sheet. Calling exec (and setting modality) will win over window flags, so in this case, we now recreate the window as a normal app-modal dialog. Task: 254524 Reviewed-by: Trenton Schulz --- doc/src/qnamespace.qdoc | 5 ++++- src/gui/kernel/qwidget.cpp | 4 ++++ src/gui/kernel/qwidget_mac.mm | 51 +++++++++++++++++++++++++------------------ 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index ca5c981..5858b4b 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -1861,7 +1861,10 @@ We refer to a top-level window that has a parent as a \e secondary window. - \value Sheet Indicates that the widget is a Macintosh sheet. + \value Sheet Indicates that the window is a Macintosh sheet. Since + using a sheet implies window modality, the recommended + way is to use QWidget::setWindowModality(), or + QDialog::open(), instead. \value Drawer Indicates that the widget is a Macintosh drawer. diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index fb9084e..1e0f09c 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -9801,6 +9801,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader)) ? Qt::WindowModal : Qt::ApplicationModal; + // Some window managers does not allow us to enter modal after the + // window is showing. Therefore, to be consistent, we cannot call + // QApplicationPrivate::enterModal(this) here. The window must be + // hidden before changing modality. } if (testAttribute(Qt::WA_WState_Created)) { // don't call setModal_sys() before create_sys() diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index f96d061..0a31a28 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4750,31 +4750,40 @@ void QWidgetPrivate::setModal_sys() || (primaryWindow && primaryWindow->windowModality() == Qt::WindowModal)){ // Window should be window-modal (which implies a sheet). if (old_wclass != kSheetWindowClass){ - // We cannot convert a created window to a sheet. So we recreate the window: + // We cannot convert a created window to a sheet. + // So we recreate the window: recreateMacWindow(); return; } - } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { - if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ - // Only change the class to kMovableModalWindowClass if the no explicit jewels - // are set (kMovableModalWindowClass can't contain them), and the current window class - // can be converted to modal (according to carbon doc). Mind the order of - // HIWindowChangeClass and ChangeWindowAttributes. - WindowGroupRef group = GetWindowGroup(windowRef); - HIWindowChangeClass(windowRef, kMovableModalWindowClass); - quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; - ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); - ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); - // If the window belongs to a qt-created group, set that group once more: - if (data.window_flags & Qt::WindowStaysOnTopHint - || q->windowType() == Qt::Popup - || q->windowType() == Qt::ToolTip) - SetWindowGroup(windowRef, group); + } else { + // Window should be application-modal (which implies NOT using a sheet). + if (old_wclass == kSheetWindowClass){ + // We cannot convert a sheet to a window. + // So we recreate the window: + recreateMacWindow(); + return; + } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { + if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ + // Only change the class to kMovableModalWindowClass if the no explicit jewels + // are set (kMovableModalWindowClass can't contain them), and the current window class + // can be converted to modal (according to carbon doc). Mind the order of + // HIWindowChangeClass and ChangeWindowAttributes. + WindowGroupRef group = GetWindowGroup(windowRef); + HIWindowChangeClass(windowRef, kMovableModalWindowClass); + quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; + ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); + ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); + // If the window belongs to a qt-created group, set that group once more: + if (data.window_flags & Qt::WindowStaysOnTopHint + || q->windowType() == Qt::Popup + || q->windowType() == Qt::ToolTip) + SetWindowGroup(windowRef, group); + } + // Popups are usually handled "special" and are never modal. + Qt::WindowType winType = q->windowType(); + if (winType != Qt::Popup && winType != Qt::ToolTip) + SetWindowModality(windowRef, kWindowModalityAppModal, 0); } - // Popups are usually handled "special" and are never modal. - Qt::WindowType winType = q->windowType(); - if (winType != Qt::Popup && winType != Qt::ToolTip) - SetWindowModality(windowRef, kWindowModalityAppModal, 0); } } else if (windowRef) { if (old_wclass == kSheetWindowClass){ -- cgit v0.12