diff --git a/README.md b/README.md
index 1b4b41452..0003c9ba2 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
-## [Telegram Desktop](https://tdesktop.com) – Official Telegram Messenger app
+# [Telegram Desktop][telegram_desktop] – Official Messenger
-This is complete source code and build instructions for alpha version of official desktop client for [Telegram](https://telegram.org) messenger, based on [Telegram API](https://core.telegram.org/) and [MTProto](https://core.telegram.org/mtproto) secure protocol.
+This is the complete source code and the build instructions for the alpha version of the official desktop client for the [Telegram][telegram] messenger, based on the [Telegram API][telegram_api] and the [MTProto][telegram_proto] secure protocol.
-Source code is published under GPL v3, license is available [here](https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE).
+The source code is published under GPL v3, the license is available [here][license].
-###Supported systems
+## Supported systems
* Windows XP - Windows 10 (**not** RT)
* Mac OS X 10.8 - Mac OS X 10.10
@@ -12,9 +12,9 @@ Source code is published under GPL v3, license is available [here](https://githu
* Ubuntu 12.04 - Ubuntu 14.04
* Fedora 22
-###Third-party
+## Third-party libraries
-* Qt 5.3.2 and 5.5.0, slightly patched ([LGPL](http://qt-project.org/doc/qt-5/lgpl.html))
+* Qt 5.3.2 and 5.5.0, slightly patched ([LGPL](http://doc.qt.io/qt-5/licensing.html))
* OpenSSL 1.0.1g ([OpenSSL License](https://www.openssl.org/source/license.html))
* zlib 1.2.8 ([zlib License](http://www.zlib.net/zlib_license.html))
* libexif 0.6.20 ([LGPL](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html))
@@ -25,75 +25,84 @@ Source code is published under GPL v3, license is available [here](https://githu
* FFmpeg ([LGPL](https://www.ffmpeg.org/legal.html))
* Open Sans font ([Apache License](http://www.apache.org/licenses/LICENSE-2.0.html))
-###[Build instructions for Visual Studio 2013](https://github.com/telegramdesktop/tdesktop/blob/master/MSVC.md)
+## Build instructions
-###[Build instructions for XCode 6.4](https://github.com/telegramdesktop/tdesktop/blob/master/XCODE.md)
+* [Visual Studio 2013][msvc]
+* [XCode 6.4][xcode]
+* [XCode 6.4 for OS X 10.6 and 10.7][xcode_old]
+* [Qt Creator 3.2.0 Ubuntu][qtcreator]
-###[Build instructions for XCode 6.4 for OS X 10.6 and 10.7](https://github.com/telegramdesktop/tdesktop/blob/master/XCODEold.md)
+## Projects in Telegram solution
-###[Build instructions for Qt Creator 3.2.0 Ubuntu](https://github.com/telegramdesktop/tdesktop/blob/master/QTCREATOR.md)
+* ### Telegram
-##Projects in Telegram solution
+ [Telegram Desktop][telegram_desktop] messenger
-####Telegram
+* ### Updater
-tdesktop messenger
+ A little app, that is launched by Telegram when update is ready, replaces all files and launches it back.
-####Updater
+* ### Packer
-little app, that is launched by Telegram when update is ready, replaces all files and launches it back
+ Compiles given files to single update file, compresses it with lzma and signs with a private key. It is not built in **Debug** and **Release** configurations of Telegram solution, because private key is inaccessible.
-####Packer
+* ### Prepare
-compiles given files to single update file, compresses it with lzma and signs with a private key, it is not built in **Debug** and **Release** configurations of Telegram solution, because private key is inaccessible
+ Prepares a release for deployment, puts all current files to deploy/{version} folder.
-####Prepare
+ **Windows**:
+ * tsetup{version}.exe installer
+ * Telegram.exe
+ * Telegram.pdb (debug info for crash minidumps view)
+ * tupdate{updversion} binary lzma update archive
-prepares a release for deployment, puts all files to deploy/{version} folder, for Win:
-* current tsetup{version}exe installer
-* current Telegram.exe
-* current Telegram.pdb (debug info for crash minidumps view)
-* current tupdate{updversion} binary lzma update archive
+ **Mac**:
+ * tsetup{version}.dmg
+ * Telegram.app
+ * tmacupd{updversion} binary lzma update archive
-for Mac:
-* current tsetup{version}dmg
-* current Telegram.app
-* current tmacupd{updversion} binary lzma update archive
+* ### MetaEmoji
-####MetaEmoji
+ Creates four sprites and text2emoji replace code
+ * SourceFiles/art/emoji.png
+ * SourceFiles/art/emoji_125x.png
+ * SourceFiles/art/emoji_150x.png
+ * SourceFiles/art/emoji_200x.png
+ * SourceFiles/art/emoji_250x.png
+ * SourceFiles/gui/emoji_config.cpp
-creates four sprites and text2emoji replace code
-* SourceFiles/art/emoji.png
-* SourceFiles/art/emoji_125x.png
-* SourceFiles/art/emoji_150x.png
-* SourceFiles/art/emoji_200x.png
-* SourceFiles/art/emoji_250x.png
-* SourceFiles/gui/emoji_config.cpp
+* ### MetaStyle
-####MetaStyle
+ From two files and two sprites
+ * Resources/style_classes.txt
+ * Resources/style.txt
+ * SourceFiles/art/sprite.png
+ * SourceFiles/art/sprite_200x.png
-from two files and two sprites
-* Resources/style_classes.txt
-* Resources/style.txt
-* SourceFiles/art/sprite.png
-* SourceFiles/art/sprite_200x.png
+ Creates two other sprites, four sprite grids and style constants code
+ * SourceFiles/art/sprite_125x.png
+ * SourceFiles/art/sprite_150x.png
+ * SourceFiles/art/grid.png
+ * SourceFiles/art/grid_125x.png
+ * SourceFiles/art/grid_150x.png
+ * SourceFiles/art/grid_200x.png
+ * GeneratedFiles/style_classes.h
+ * GeneratedFiles/style_auto.h
+ * GeneratedFiles/style_auto.cpp
-creates two other sprites, four sprite grids and style constants code
-* SourceFiles/art/sprite_125x.png
-* SourceFiles/art/sprite_150x.png
-* SourceFiles/art/grid.png
-* SourceFiles/art/grid_125x.png
-* SourceFiles/art/grid_150x.png
-* SourceFiles/art/grid_200x.png
-* GeneratedFiles/style_classes.h
-* GeneratedFiles/style_auto.h
-* GeneratedFiles/style_auto.cpp
+* ### MetaLang
-####MetaLang
+ Creates from languagepack file `Resources/lang.txt` language constants code and language file parse code:
+ * GeneratedFiles/lang.h
+ * GeneratedFiles/lang.cpp
-from langpack file
-* Resources/lang.txt
-
-creates lang constants code and lang file parse code
-* GeneratedFiles/lang.h
-* GeneratedFiles/lang.cpp
+[//]: # (LINKS)
+[telegram]: https://telegram.org
+[telegram_desktop]: https://desktop.telegram.org
+[telegram_api]: https://core.telegram.org
+[telegram_proto]: https://core.telegram.org/mtproto
+[license]: LICENSE
+[msvc]: MSVC.md
+[xcode]: XCODE.md
+[xcode_old]: XCODEold.md
+[qtcreator]: qtcreator.md
\ No newline at end of file
diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat
index c832556d5..7774c249d 100644
--- a/Telegram/PrepareWin.bat
+++ b/Telegram/PrepareWin.bat
@@ -1,10 +1,10 @@
@echo OFF
set "AppVersionStrMajor=0.8"
-set "AppVersion=8056"
-set "AppVersionStrSmall=0.8.56"
-set "AppVersionStr=0.8.56"
-set "AppVersionStrFull=0.8.56.0"
+set "AppVersion=8057"
+set "AppVersionStrSmall=0.8.57"
+set "AppVersionStr=0.8.57"
+set "AppVersionStrFull=0.8.57.0"
set "DevChannel=0"
if %DevChannel% neq 0 goto preparedev
diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings
index cb1abb828..078989e2f 100644
--- a/Telegram/Resources/lang.strings
+++ b/Telegram/Resources/lang.strings
@@ -494,6 +494,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Report Spam";
"lng_report_spam_hide" = "Hide";
"lng_report_spam_thanks" = "Thank you for your report!";
+"lng_report_spam_sure" = "Are you sure you want\nto report spam from this user?";
+"lng_report_spam_sure_group" = "Are you sure you want\nto report spam in this group?";
+"lng_report_spam_ok" = "Report";
"lng_cant_send_to_not_contact" = "Sorry, you can only send messages to\nmutual contacts at the moment. {more_info}";
"lng_cant_invite_not_contact" = "Sorry, you can only add mutual contacts\nto groups at the moment. {more_info}";
"lng_cant_more_info" = "More info »";
diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index ebc06ab4d..7e2fca159 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
-static const int32 AppVersion = 8056;
-static const wchar_t *AppVersionStr = L"0.8.56";
+static const int32 AppVersion = 8057;
+static const wchar_t *AppVersionStr = L"0.8.57";
static const bool DevVersion = false;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 00e0e3c23..46d3e3b89 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -6091,7 +6091,7 @@ bool HistoryReply::updateReplyTo(bool force) {
}
if (force) {
initDimensions();
- if (App::main()) App::main()->msgUpdated(history()->peer->id, this);
+ if (App::main()) App::main()->itemResized(this);
}
return (replyToMsg || !replyToMsgId);
}
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index f99b5f232..1e4126e59 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -544,6 +544,7 @@ void HistoryList::onDragExec() {
}
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
+ if (App::main()) App::main()->updateAfterDrag();
return;
} else {
HistoryItem *pressedLnkItem = App::pressedLinkItem(), *pressedItem = App::pressedItem();
@@ -575,6 +576,7 @@ void HistoryList::onDragExec() {
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
+ if (App::main()) App::main()->updateAfterDrag();
return;
}
}
@@ -2988,6 +2990,10 @@ void HistoryWidget::contactsReceived() {
updateControlsVisibility();
}
+void HistoryWidget::updateAfterDrag() {
+ if (_list) _list->dragActionUpdate(QCursor::pos());
+}
+
void HistoryWidget::updateReportSpamStatus() {
if (!_peer || (_peer->isUser() && (peerToUser(_peer->id) == MTP::authedId() || isNotificationsUser(_peer->id) || isServiceUser(_peer->id) || _peer->asUser()->botInfo))) {
_reportSpamStatus = dbiprsNoButton;
@@ -4752,10 +4758,18 @@ void HistoryWidget::onAudioFailed(const FullMsgId &newId) {
}
void HistoryWidget::onReportSpamClicked() {
+ ConfirmBox *box = new ConfirmBox(lang(_peer->isUser() ? lng_report_spam_sure : lng_report_spam_sure_group), lang(lng_report_spam_ok));
+ connect(box, SIGNAL(confirmed()), this, SLOT(onReportSpamSure()));
+ App::wnd()->showLayer(box);
+ _clearPeer = _peer;
+}
+
+void HistoryWidget::onReportSpamSure() {
if (_reportSpamRequest) return;
- if (_peer->isUser()) MTP::send(MTPcontacts_Block(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _peer), RPCFailHandlerPtr(), 0, 5);
- _reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_peer->input), rpcDone(&HistoryWidget::reportSpamDone, _peer), rpcFail(&HistoryWidget::reportSpamFail));
+ App::wnd()->hideLayer();
+ if (_clearPeer->isUser()) MTP::send(MTPcontacts_Block(_clearPeer->asUser()->inputUser), rpcDone(&HistoryWidget::blockDone, _clearPeer), RPCFailHandlerPtr(), 0, 5);
+ _reportSpamRequest = MTP::send(MTPmessages_ReportSpam(_clearPeer->input), rpcDone(&HistoryWidget::reportSpamDone, _clearPeer), rpcFail(&HistoryWidget::reportSpamFail));
}
void HistoryWidget::reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId req) {
@@ -4796,10 +4810,10 @@ void HistoryWidget::onReportSpamClear() {
}
void HistoryWidget::onReportSpamClearSure() {
+ App::wnd()->hideLayer();
if (_clearPeer->isUser()) {
App::main()->deleteConversation(_clearPeer);
} else if (_clearPeer->isChat()) {
- App::wnd()->hideLayer();
App::main()->showDialogs();
MTP::send(MTPmessages_DeleteChatUser(_clearPeer->asChat()->inputChat, App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _clearPeer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _clearPeer));
} else if (_clearPeer->isChannel()) { // CHANNELS_UX
diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h
index 4cc73139d..858120c1d 100644
--- a/Telegram/SourceFiles/historywidget.h
+++ b/Telegram/SourceFiles/historywidget.h
@@ -519,6 +519,8 @@ public:
void contactsReceived();
void updateToEndVisibility();
+ void updateAfterDrag();
+
~HistoryWidget();
signals:
@@ -557,6 +559,7 @@ public slots:
void onAudioFailed(const FullMsgId &msgId);
void onReportSpamClicked();
+ void onReportSpamSure();
void onReportSpamHide();
void onReportSpamClear();
void onReportSpamClearSure();
diff --git a/Telegram/SourceFiles/langs/lang_de.strings b/Telegram/SourceFiles/langs/lang_de.strings
index 44360ddbc..bdb9b05ed 100644
--- a/Telegram/SourceFiles/langs/lang_de.strings
+++ b/Telegram/SourceFiles/langs/lang_de.strings
@@ -487,7 +487,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Spam melden";
"lng_report_spam_hide" = "Schließen";
-"lng_report_spam_thanks" = "Danke für die Meldung!";
+"lng_report_spam_thanks" = "Danke!";
+"lng_report_spam_sure" = "Möchtest du wirklich Spam\nvon diesem Nutzer melden?";
+"lng_report_spam_sure_group" = "Möchtest du wirklich Spam\nin dieser Gruppe melden?";
+"lng_report_spam_ok" = "Melden";
"lng_cant_send_to_not_contact" = "Derzeit kannst du nur Personen schreiben, wenn ihr eure Nummern ausgetauscht habt. {more_info}";
"lng_cant_invite_not_contact" = "Du kannst nur Personen hinzufügen, wenn ihr eure Nummern ausgetauscht habt. {more_info}";
"lng_cant_more_info" = "Weitere Infos »";
diff --git a/Telegram/SourceFiles/langs/lang_es.strings b/Telegram/SourceFiles/langs/lang_es.strings
index 73e7a462b..a6138e500 100644
--- a/Telegram/SourceFiles/langs/lang_es.strings
+++ b/Telegram/SourceFiles/langs/lang_es.strings
@@ -488,6 +488,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Reportar spam";
"lng_report_spam_hide" = "Ocultar";
"lng_report_spam_thanks" = "¡Gracias por tu reporte!";
+"lng_report_spam_sure" = "¿Quieres reportar el\nspam de este usuario?";
+"lng_report_spam_sure_group" = "¿Quieres reportar el\nspam en este grupo?";
+"lng_report_spam_ok" = "Reportar";
"lng_cant_send_to_not_contact" = "Por ahora, sólo puedes enviar mensajes\na contactos mutuos. {more_info}";
"lng_cant_invite_not_contact" = "Por ahora, sólo puedes añadir contactos \nmutuos a grupos. {more_info}";
"lng_cant_more_info" = "Más información »";
@@ -632,7 +635,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_about_text" = "Aplicación oficial basada en [a href=\"https://core.telegram.org/mtproto\"]MTProto[/a] y la [a href=\"https://core.telegram.org/api\"]\nAPI de Telegram[/a] para velocidad y seguridad.\n\nSoftware bajo licencia [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] versión 3.\nCódigo fuente disponible en [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a].";
"lng_about_done" = "Hecho";
-"lng_search_found_results" = "{count:No se encontraron mensajes|Found # mensaje|Found # mensajes}";
+"lng_search_found_results" = "{count:No se encontraron mensajes|# mensaje encontrado|# mensajes encontrados}";
"lng_search_global_results" = "Resultados de la búsqueda global";
"lng_media_save_progress" = "{ready} de {total} {mb}";
diff --git a/Telegram/SourceFiles/langs/lang_it.strings b/Telegram/SourceFiles/langs/lang_it.strings
index 712aeb38f..fc9eed362 100644
--- a/Telegram/SourceFiles/langs/lang_it.strings
+++ b/Telegram/SourceFiles/langs/lang_it.strings
@@ -488,6 +488,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Segnala spam";
"lng_report_spam_hide" = "Nascondi";
"lng_report_spam_thanks" = "Grazie per la tua segnalazione!";
+"lng_report_spam_sure" = "Sei sicuro di voler segnalare\nquesto utente come spam?";
+"lng_report_spam_sure_group" = "Sei sicuro di voler segnalare\ndello spam in questo gruppo?";
+"lng_report_spam_ok" = "Segnala";
"lng_cant_send_to_not_contact" = "Spiacenti, ma al momento puoi scrivere\nsolo a contatti in comune. {more_info}";
"lng_cant_invite_not_contact" = "Spiacenti, ma al momento puoi aggiungere\nai gruppi solo a contatti in comune. {more_info}";
"lng_cant_more_info" = "Più info »";
diff --git a/Telegram/SourceFiles/langs/lang_ko.strings b/Telegram/SourceFiles/langs/lang_ko.strings
index b8bfde487..3c08daee9 100644
--- a/Telegram/SourceFiles/langs/lang_ko.strings
+++ b/Telegram/SourceFiles/langs/lang_ko.strings
@@ -488,6 +488,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "스팸 신고";
"lng_report_spam_hide" = "숨기기";
"lng_report_spam_thanks" = "신고해주셔서 감사합니다!";
+"lng_report_spam_sure" = "선택한 사용자 메사자를\n스팸으로 신고하겠습니까?";
+"lng_report_spam_sure_group" = "선택한 그룹 메시지를\n스팸으로 신고하시겠습니까?";
+"lng_report_spam_ok" = "신고하기";
"lng_cant_send_to_not_contact" = "죄송하지만, 현재 서로 연락처가 추가된\n회원들끼리만 전송이 가능합니다. {more_info}";
"lng_cant_invite_not_contact" = "죄송하지만, 현재 서로 연락처가 추가된\n회원들끼리만 추가 가능합니다. {more_info}";
"lng_cant_more_info" = "자세한 정보 »";
diff --git a/Telegram/SourceFiles/langs/lang_nl.strings b/Telegram/SourceFiles/langs/lang_nl.strings
index 16703c5d9..bbd0d0323 100644
--- a/Telegram/SourceFiles/langs/lang_nl.strings
+++ b/Telegram/SourceFiles/langs/lang_nl.strings
@@ -488,6 +488,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Spam melden";
"lng_report_spam_hide" = "Verbergen";
"lng_report_spam_thanks" = "Bedankt voor je melding!";
+"lng_report_spam_sure" = "Spam van deze\ngebruiker echt melden? ";
+"lng_report_spam_sure_group" = "Spam van deze\ngroep echt melden? ";
+"lng_report_spam_ok" = "Melden";
"lng_cant_send_to_not_contact" = "Op dit moment kun je alleen berichten\nversturen naar onderlinge contacten. {more_info}";
"lng_cant_invite_not_contact" = "Op dit moment kun je alleen onderlinge\ncontacten aan groepen toevoegen. {more_info}";
"lng_cant_more_info" = "Meer informatie »";
diff --git a/Telegram/SourceFiles/langs/lang_pt_BR.strings b/Telegram/SourceFiles/langs/lang_pt_BR.strings
index 84b3bd4c3..ceb1127f8 100644
--- a/Telegram/SourceFiles/langs/lang_pt_BR.strings
+++ b/Telegram/SourceFiles/langs/lang_pt_BR.strings
@@ -488,6 +488,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_report_spam" = "Reportar Spam";
"lng_report_spam_hide" = "Ocultar";
"lng_report_spam_thanks" = "Obrigado por reportar!";
+"lng_report_spam_sure" = "Tem certeza que deseja\nreportar spam deste usuário?";
+"lng_report_spam_sure_group" = "Tem certeza que seseja\nreportar por spam nesse grupo?";
+"lng_report_spam_ok" = "Reportar";
"lng_cant_send_to_not_contact" = "Você só pode enviar mensagens para\ncontatos mútuos no momento. {more_info}";
"lng_cant_invite_not_contact" = "Você só pode adicionar contatos\nmútuos ao grupo no momento. {more_info}";
"lng_cant_more_info" = "Informações »";
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index c95b7bc43..6d35b2580 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -1372,6 +1372,7 @@ void MainWidget::itemResized(HistoryItem *row, bool scrollToIt) {
if (overview) {
overview->itemResized(row, scrollToIt);
}
+ if (row) msgUpdated(row->history()->peer->id, row);
}
bool MainWidget::overviewFailed(PeerData *peer, const RPCError &error, mtpRequestId req) {
@@ -2107,6 +2108,14 @@ void MainWidget::contactsReceived() {
history.contactsReceived();
}
+void MainWidget::updateAfterDrag() {
+ if (overview) {
+ overview->updateAfterDrag();
+ } else {
+ history.updateAfterDrag();
+ }
+}
+
void MainWidget::showPeerHistory(quint64 peerId, qint32 showAtMsgId, bool back) {
if (!back && (!peerId || (_stack.size() == 1 && _stack[0]->type() == HistoryStackItem && _stack[0]->peer->id == peerId))) {
back = true;
@@ -4120,6 +4129,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (ChannelData *channel = App::channelLoaded(d.vchannel_id.v)) {
if (d.vgroup.type() == mtpc_messageGroup) {
const MTPDmessageGroup &data(d.vgroup.c_messageGroup());
+ // CHANNELS_FULL
}
}
} break;
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index 13c014a88..07f2e40b9 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -383,6 +383,7 @@ public:
void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0);
void feedUpdate(const MTPUpdate &update);
+ void updateAfterDrag();
~MainWidget();
diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp
index 3fad64c8d..2d3767c87 100644
--- a/Telegram/SourceFiles/overviewwidget.cpp
+++ b/Telegram/SourceFiles/overviewwidget.cpp
@@ -820,7 +820,7 @@ void OverviewInner::onDragExec() {
}
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
- dragActionUpdate(QCursor::pos());
+ if (App::main()) App::main()->updateAfterDrag();
return;
} else {
HistoryItem *pressedLnkItem = App::pressedLinkItem(), *pressedItem = App::pressedItem();
@@ -847,7 +847,7 @@ void OverviewInner::onDragExec() {
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
- dragActionUpdate(QCursor::pos());
+ if (App::main()) App::main()->updateAfterDrag();
return;
}
}
@@ -2855,6 +2855,10 @@ void OverviewWidget::updateScrollColors() {
_scroll.updateColors(App::historyScrollBarColor(), App::historyScrollBgColor(), App::historyScrollBarOverColor(), App::historyScrollBgOverColor());
}
+void OverviewWidget::updateAfterDrag() {
+ _inner.dragActionUpdate(QCursor::pos());
+}
+
OverviewWidget::~OverviewWidget() {
onClearSelected();
updateTopBarSelection();
diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h
index 6496f7c78..7a7926e9d 100644
--- a/Telegram/SourceFiles/overviewwidget.h
+++ b/Telegram/SourceFiles/overviewwidget.h
@@ -312,6 +312,8 @@ public:
void updateScrollColors();
+ void updateAfterDrag();
+
~OverviewWidget();
public slots:
diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist
index 529320931..4968406f2 100644
--- a/Telegram/Telegram.plist
+++ b/Telegram/Telegram.plist
@@ -11,7 +11,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.8.56
+ 0.8.57
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
CFBundleSignature
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index ec03f392f..ba55f0bae 100644
Binary files a/Telegram/Telegram.rc and b/Telegram/Telegram.rc differ
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index 522b6b901..ab30bcf43 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -1697,7 +1697,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 0.8.56;
+ CURRENT_PROJECT_VERSION = 0.8.57;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -1715,7 +1715,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 0.8.56;
+ CURRENT_PROJECT_VERSION = 0.8.57;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1741,10 +1741,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 0.8.56;
+ CURRENT_PROJECT_VERSION = 0.8.57;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
- DYLIB_CURRENT_VERSION = 0.8.56;
+ DYLIB_CURRENT_VERSION = 0.8.57;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1875,10 +1875,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 0.8.56;
+ CURRENT_PROJECT_VERSION = 0.8.57;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
- DYLIB_CURRENT_VERSION = 0.8.56;
+ DYLIB_CURRENT_VERSION = 0.8.57;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
diff --git a/Telegram/Version.sh b/Telegram/Version.sh
index 873248d22..321f91462 100755
--- a/Telegram/Version.sh
+++ b/Telegram/Version.sh
@@ -1,2 +1,2 @@
-echo 0.8 8056 0.8.56 0
+echo 0.8 8057 0.8.57 0
# AppVersionStrMajor AppVersion AppVersionStr DevChannel
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.cpp b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.cpp
new file mode 100644
index 000000000..c39c6a14c
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+class QBackingStorePrivate
+{
+public:
+ QBackingStorePrivate(QWindow *w)
+ : window(w)
+ {
+ }
+
+ QWindow *window;
+ QPlatformBackingStore *platformBackingStore;
+ QRegion staticContents;
+ QSize size;
+};
+
+/*!
+ \class QBackingStore
+ \since 5.0
+ \inmodule QtGui
+
+ \brief The QBackingStore class provides a drawing area for QWindow.
+
+ QBackingStore enables the use of QPainter to paint on a QWindow with type
+ RasterSurface. The other way of rendering to a QWindow is through the use
+ of OpenGL with QOpenGLContext.
+
+ A QBackingStore contains a buffered representation of the window contents,
+ and thus supports partial updates by using QPainter to only update a sub
+ region of the window contents.
+
+ QBackingStore might be used by an application that wants to use QPainter
+ without OpenGL acceleration and without the extra overhead of using the
+ QWidget or QGraphicsView UI stacks. For an example of how to use
+ QBackingStore see the \l{Raster Window Example}.
+*/
+
+/*!
+ Flushes the given \a region from the specified window \a win onto the
+ screen.
+
+ Note that the \a offset parameter is currently unused.
+*/
+void QBackingStore::flush(const QRegion ®ion, QWindow *win, const QPoint &offset)
+{
+ if (!win)
+ win = window();
+ if (!win->handle()) {
+ qWarning() << "QBackingStore::flush() called for "
+ << win << " which does not have a handle.";
+ return;
+ }
+
+#ifdef QBACKINGSTORE_DEBUG
+ if (win && win->isTopLevel() && !qt_window_private(win)->receivedExpose) {
+ qWarning().nospace() << "QBackingStore::flush() called with non-exposed window "
+ << win << ", behavior is undefined";
+ }
+#endif
+
+ d_ptr->platformBackingStore->flush(win, region, offset);
+}
+
+/*!
+ \fn QPaintDevice* QBackingStore::paintDevice()
+
+ Implement this function to return the appropriate paint device.
+*/
+QPaintDevice *QBackingStore::paintDevice()
+{
+ return d_ptr->platformBackingStore->paintDevice();
+}
+
+/*!
+ Constructs an empty surface for the given top-level \a window.
+*/
+QBackingStore::QBackingStore(QWindow *window)
+ : d_ptr(new QBackingStorePrivate(window))
+{
+ d_ptr->platformBackingStore = QGuiApplicationPrivate::platformIntegration()->createPlatformBackingStore(window);
+}
+
+/*!
+ Destroys this surface.
+*/
+QBackingStore::~QBackingStore()
+{
+ delete d_ptr->platformBackingStore;
+}
+
+/*!
+ Returns a pointer to the top-level window associated with this
+ surface.
+*/
+QWindow* QBackingStore::window() const
+{
+ return d_ptr->window;
+}
+
+/*!
+ This function is called before painting onto the surface begins,
+ with the \a region in which the painting will occur.
+
+ \sa endPaint(), paintDevice()
+*/
+
+void QBackingStore::beginPaint(const QRegion ®ion)
+{
+ d_ptr->platformBackingStore->beginPaint(region);
+}
+
+void QBackingStore::beforeBeginPaint(QWindow *win)
+{
+ if (!win)
+ win = window();
+ if (!win->handle())
+ return;
+ d_ptr->platformBackingStore->beforeBeginPaint(win);
+}
+
+/*!
+ This function is called after painting onto the surface has ended.
+
+ \sa beginPaint(), paintDevice()
+*/
+void QBackingStore::endPaint()
+{
+ d_ptr->platformBackingStore->endPaint();
+}
+
+void QBackingStore::afterEndPaint(QWindow *win)
+{
+ if (!win)
+ win = window();
+ if (!win->handle())
+ return;
+ d_ptr->platformBackingStore->afterEndPaint(win);
+}
+
+/*!
+ Sets the size of the windowsurface to be \a size.
+
+ \sa size()
+*/
+void QBackingStore::resize(const QSize &size)
+{
+ d_ptr->size = size;
+ d_ptr->platformBackingStore->resize(size, d_ptr->staticContents);
+}
+
+/*!
+ Returns the current size of the windowsurface.
+*/
+QSize QBackingStore::size() const
+{
+ return d_ptr->size;
+}
+
+/*!
+ Scrolls the given \a area \a dx pixels to the right and \a dy
+ downward; both \a dx and \a dy may be negative.
+
+ Returns \c true if the area was scrolled successfully; false otherwise.
+*/
+bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
+{
+ Q_UNUSED(area);
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+
+ return d_ptr->platformBackingStore->scroll(area, dx, dy);
+}
+
+void QBackingStore::setStaticContents(const QRegion ®ion)
+{
+ d_ptr->staticContents = region;
+}
+
+QRegion QBackingStore::staticContents() const
+{
+ return d_ptr->staticContents;
+}
+
+bool QBackingStore::hasStaticContents() const
+{
+ return !d_ptr->staticContents.isEmpty();
+}
+
+void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
+{
+ // make sure we don't detach
+ uchar *mem = const_cast(const_cast(img).bits());
+
+ int lineskip = img.bytesPerLine();
+ int depth = img.depth() >> 3;
+
+ const QRect imageRect(0, 0, img.width(), img.height());
+ const QRect r = rect & imageRect & imageRect.translated(-offset);
+ const QPoint p = rect.topLeft() + offset;
+
+ if (r.isEmpty())
+ return;
+
+ const uchar *src;
+ uchar *dest;
+
+ if (r.top() < p.y()) {
+ src = mem + r.bottom() * lineskip + r.left() * depth;
+ dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
+ lineskip = -lineskip;
+ } else {
+ src = mem + r.top() * lineskip + r.left() * depth;
+ dest = mem + p.y() * lineskip + p.x() * depth;
+ }
+
+ const int w = r.width();
+ int h = r.height();
+ const int bytes = w * depth;
+
+ // overlapping segments?
+ if (offset.y() == 0 && qAbs(offset.x()) < w) {
+ do {
+ ::memmove(dest, src, bytes);
+ dest += lineskip;
+ src += lineskip;
+ } while (--h);
+ } else {
+ do {
+ ::memcpy(dest, src, bytes);
+ dest += lineskip;
+ src += lineskip;
+ } while (--h);
+ }
+}
+
+QPlatformBackingStore *QBackingStore::handle() const
+{
+ return d_ptr->platformBackingStore;
+}
+
+QT_END_NAMESPACE
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.h b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.h
new file mode 100644
index 000000000..faa5fbcde
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qbackingstore.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBACKINGSTORE_H
+#define QBACKINGSTORE_H
+
+#include
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+
+class QRegion;
+class QRect;
+class QPoint;
+class QImage;
+class QBackingStorePrivate;
+class QPlatformBackingStore;
+
+class Q_GUI_EXPORT QBackingStore
+{
+public:
+ explicit QBackingStore(QWindow *window);
+ ~QBackingStore();
+
+ QWindow *window() const;
+
+ QPaintDevice *paintDevice();
+
+ // 'window' can be a child window, in which case 'region' is in child window coordinates and
+ // offset is the (child) window's offset in relation to the window surface.
+ void flush(const QRegion ®ion, QWindow *window = 0, const QPoint &offset = QPoint());
+
+ void resize(const QSize &size);
+ QSize size() const;
+
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ void beginPaint(const QRegion &);
+ void beforeBeginPaint(QWindow *window);
+ void endPaint();
+ void afterEndPaint(QWindow *window);
+
+ void setStaticContents(const QRegion ®ion);
+ QRegion staticContents() const;
+ bool hasStaticContents() const;
+
+ QPlatformBackingStore *handle() const;
+
+private:
+ QScopedPointer d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBACKINGSTORE_H
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qplatformbackingstore.h b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qplatformbackingstore.h
new file mode 100644
index 000000000..0cb1c9a7f
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/gui/painting/qplatformbackingstore.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMBACKINGSTORE_H
+#define QPLATFORMBACKINGSTORE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the QPA API and is not meant to be used
+// in applications. Usage of this API may make your code
+// source and binary incompatible with future versions of Qt.
+//
+
+#include
+#include
+
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+
+class QRegion;
+class QRect;
+class QPoint;
+class QImage;
+class QPlatformBackingStorePrivate;
+class QPlatformWindow;
+class QPlatformTextureList;
+class QPlatformTextureListPrivate;
+class QOpenGLContext;
+class QPlatformGraphicsBuffer;
+
+#ifndef QT_NO_OPENGL
+class Q_GUI_EXPORT QPlatformTextureList : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPlatformTextureList)
+public:
+ enum Flag {
+ StacksOnTop = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ explicit QPlatformTextureList(QObject *parent = 0);
+ ~QPlatformTextureList();
+
+ int count() const;
+ bool isEmpty() const { return count() == 0; }
+ GLuint textureId(int index) const;
+ QRect geometry(int index) const;
+ QRect clipRect(int index) const;
+ void *source(int index);
+ Flags flags(int index) const;
+ void lock(bool on);
+ bool isLocked() const;
+
+ void appendTexture(void *source, GLuint textureId, const QRect &geometry,
+ const QRect &clipRect = QRect(), Flags flags = 0);
+ void clear();
+
+ Q_SIGNALS:
+ void locked(bool);
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformTextureList::Flags)
+#endif
+
+class Q_GUI_EXPORT QPlatformBackingStore
+{
+public:
+ explicit QPlatformBackingStore(QWindow *window);
+ virtual ~QPlatformBackingStore();
+
+ QWindow *window() const;
+
+ virtual QPaintDevice *paintDevice() = 0;
+
+ // 'window' can be a child window, in which case 'region' is in child window coordinates and
+ // offset is the (child) window's offset in relation to the window surface.
+ virtual void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) = 0;
+#ifndef QT_NO_OPENGL
+ virtual void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
+ QPlatformTextureList *textures, QOpenGLContext *context,
+ bool translucentBackground);
+ virtual QImage toImage() const;
+ enum TextureFlag {
+ TextureSwizzle = 0x01,
+ TextureFlip = 0x02
+ };
+ Q_DECLARE_FLAGS(TextureFlags, TextureFlag)
+ virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
+#endif
+
+ virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
+
+ virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
+
+ virtual bool scroll(const QRegion &area, int dx, int dy);
+
+ virtual void beginPaint(const QRegion &);
+ virtual void beforeBeginPaint(QWindow *window) {
+ }
+ virtual void endPaint();
+ virtual void afterEndPaint(QWindow *window) {
+ }
+
+private:
+ QPlatformBackingStorePrivate *d_ptr;
+};
+
+#ifndef QT_NO_OPENGL
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags)
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QPLATFORMBACKINGSTORE_H
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.h b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.h
new file mode 100644
index 000000000..dab59c86f
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBACKINGSTORE_COCOA_H
+#define QBACKINGSTORE_COCOA_H
+
+#include
+
+#include "qcocoawindow.h"
+#include "qnsview.h"
+
+#include
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaBackingStore : public QPlatformBackingStore
+{
+public:
+ QCocoaBackingStore(QWindow *window);
+ ~QCocoaBackingStore();
+
+ QPaintDevice *paintDevice();
+ void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset);
+ QImage toImage() const;
+ void resize (const QSize &size, const QRegion &);
+ bool scroll(const QRegion &area, int dx, int dy);
+ void beginPaint(const QRegion ®ion);
+ void beforeBeginPaint(QWindow *widget);
+ void afterEndPaint(QWindow *widget);
+ qreal getBackingStoreDevicePixelRatio();
+
+private:
+ QImage m_qImage;
+ QSize m_requestedSize;
+ bool m_imageWasEqual;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.mm
new file mode 100644
index 000000000..3a153de05
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcocoabackingstore.h"
+#include
+#include "qcocoahelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
+ : QPlatformBackingStore(window), m_imageWasEqual(false)
+{
+}
+
+QCocoaBackingStore::~QCocoaBackingStore()
+{
+}
+
+QPaintDevice *QCocoaBackingStore::paintDevice()
+{
+ QCocoaWindow *cocoaWindow = static_cast(window()->handle());
+ int windowDevicePixelRatio = int(cocoaWindow->devicePixelRatio());
+
+ // Receate the backing store buffer if the effective buffer size has changed,
+ // either due to a window resize or devicePixelRatio change.
+ QSize effectiveBufferSize = m_requestedSize * windowDevicePixelRatio;
+ if (m_qImage.size() != effectiveBufferSize) {
+ QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient)
+ ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+ m_qImage = QImage(effectiveBufferSize, format);
+ m_qImage.setDevicePixelRatio(windowDevicePixelRatio);
+ if (format == QImage::Format_ARGB32_Premultiplied)
+ m_qImage.fill(Qt::transparent);
+ }
+ return &m_qImage;
+}
+
+void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint &offset)
+{
+ if (!m_qImage.isNull()) {
+ if (QCocoaWindow *cocoaWindow = static_cast(win->handle()))
+ [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset];
+ }
+}
+
+QImage QCocoaBackingStore::toImage() const
+{
+ return m_qImage;
+}
+
+void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
+{
+ m_requestedSize = size;
+}
+
+bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
+{
+ extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+ const qreal devicePixelRatio = m_qImage.devicePixelRatio();
+ QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio);
+ const QVector qrects = area.rects();
+ for (int i = 0; i < qrects.count(); ++i) {
+ const QRect &qrect = QRect(qrects.at(i).topLeft() * devicePixelRatio, qrects.at(i).size() * devicePixelRatio);
+ qt_scrollRectInImage(m_qImage, qrect, qpoint);
+ }
+ return true;
+}
+
+void QCocoaBackingStore::beginPaint(const QRegion ®ion)
+{
+ if (m_qImage.hasAlphaChannel()) {
+ QPainter p(&m_qImage);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ const QVector rects = region.rects();
+ const QColor blank = Qt::transparent;
+ for (QVector::const_iterator it = rects.begin(), end = rects.end(); it != end; ++it)
+ p.fillRect(*it, blank);
+ }
+}
+
+void QCocoaBackingStore::beforeBeginPaint(QWindow *win) {
+ m_imageWasEqual = false;
+ if (!m_qImage.isNull()) {
+ if (QCocoaWindow *cocoaWindow = static_cast(win->handle())) {
+ if ([cocoaWindow->m_qtView beforeBeginPaint:this])
+ m_imageWasEqual = true;
+ }
+ }
+}
+
+void QCocoaBackingStore::afterEndPaint(QWindow *win) {
+ if (!m_qImage.isNull()) {
+ if (QCocoaWindow *cocoaWindow = static_cast(win->handle())) {
+ if (m_imageWasEqual)
+ [cocoaWindow->m_qtView afterEndPaint:this];
+ }
+ }
+ m_imageWasEqual = false;
+}
+
+qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
+{
+ return m_qImage.devicePixelRatio();
+}
+
+QT_END_NAMESPACE
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.h b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.h
new file mode 100644
index 000000000..1940b25c9
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNSVIEW_H
+#define QNSVIEW_H
+
+#include
+
+#include
+#include
+#include
+
+#include "private/qcore_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+class QCocoaWindow;
+class QCocoaBackingStore;
+class QCocoaGLContext;
+QT_END_NAMESPACE
+
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
+
+@interface QT_MANGLE_NAMESPACE(QNSView) : NSView {
+ QImage m_backingStore;
+ qreal m_pixelRatio;
+ QPoint m_backingStoreOffset;
+ CGImageRef m_maskImage;
+ uchar *m_maskData;
+ bool m_shouldInvalidateWindowShadow;
+ QWindow *m_window;
+ QCocoaWindow *m_platformWindow;
+ NSTrackingArea *m_trackingArea;
+ Qt::MouseButtons m_buttons;
+ Qt::MouseButtons m_frameStrutButtons;
+ QString m_composingText;
+ bool m_sendKeyEvent;
+ QStringList *currentCustomDragTypes;
+ bool m_sendUpAsRightButton;
+ Qt::KeyboardModifiers currentWheelModifiers;
+ bool m_subscribesForGlobalFrameNotifications;
+#ifndef QT_NO_OPENGL
+ QCocoaGLContext *m_glContext;
+ bool m_shouldSetGLContextinDrawRect;
+#endif
+ NSString *m_inputSource;
+ QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
+ bool m_resendKeyEvent;
+ bool m_scrolling;
+ bool m_exposedOnMoveToWindow;
+}
+
+- (id)init;
+- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
+- (void) clearQWindowPointers;
+#ifndef QT_NO_OPENGL
+- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
+#endif
+- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
+- (BOOL)beforeBeginPaint:(QCocoaBackingStore *)backingStore;
+- (void)afterEndPaint:(QCocoaBackingStore *)backingStore;
+- (void)setMaskRegion:(const QRegion *)region;
+- (void)invalidateWindowShadowIfNeeded;
+- (void)drawRect:(NSRect)dirtyRect;
+- (void)updateGeometry;
+- (void)notifyWindowStateChanged:(Qt::WindowState)newState;
+- (void)windowNotification : (NSNotification *) windowNotification;
+- (void)notifyWindowWillZoom:(BOOL)willZoom;
+- (void)viewDidHide;
+- (void)viewDidUnhide;
+
+- (BOOL)isFlipped;
+- (BOOL)acceptsFirstResponder;
+- (BOOL)becomeFirstResponder;
+- (BOOL)hasMask;
+- (BOOL)isOpaque;
+
+- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint;
+
+- (void)resetMouseButtons;
+
+- (void)handleMouseEvent:(NSEvent *)theEvent;
+- (void)mouseDown:(NSEvent *)theEvent;
+- (void)mouseDragged:(NSEvent *)theEvent;
+- (void)mouseUp:(NSEvent *)theEvent;
+- (void)mouseMovedImpl:(NSEvent *)theEvent;
+- (void)mouseEnteredImpl:(NSEvent *)theEvent;
+- (void)mouseExitedImpl:(NSEvent *)theEvent;
+- (void)cursorUpdateImpl:(NSEvent *)theEvent;
+- (void)rightMouseDown:(NSEvent *)theEvent;
+- (void)rightMouseDragged:(NSEvent *)theEvent;
+- (void)rightMouseUp:(NSEvent *)theEvent;
+- (void)otherMouseDown:(NSEvent *)theEvent;
+- (void)otherMouseDragged:(NSEvent *)theEvent;
+- (void)otherMouseUp:(NSEvent *)theEvent;
+- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
+
+- (void)handleTabletEvent: (NSEvent *)theEvent;
+- (void)tabletPoint: (NSEvent *)theEvent;
+- (void)tabletProximity: (NSEvent *)theEvent;
+
+- (int) convertKeyCode : (QChar)keyCode;
++ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags;
+- (void)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
+- (void)keyDown:(NSEvent *)theEvent;
+- (void)keyUp:(NSEvent *)theEvent;
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
+
+- (void)registerDragTypes;
+- (NSDragOperation)handleDrag:(id )sender;
+
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSView);
+
+#endif //QNSVIEW_H
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.mm b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.mm
index cfc8705e4..f31ad9e5a 100644
--- a/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.mm
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/plugins/platforms/cocoa/qnsview.mm
@@ -484,6 +484,20 @@ QT_WARNING_POP
}
}
+- (BOOL) beforeBeginPaint:(QCocoaBackingStore *)backingStore
+{
+ if (!m_backingStore.isNull() && m_backingStore.constBits() == backingStore->toImage().constBits()) {
+ m_backingStore = QImage();
+ return true;
+ }
+ return false;
+}
+
+- (void) afterEndPaint:(QCocoaBackingStore *)backingStore
+{
+ m_backingStore = backingStore->toImage();
+}
+
- (BOOL) hasMask
{
return m_maskImage != 0;
diff --git a/Telegram/_qt_5_5_0_patch/qtbase/src/widgets/kernel/qwidgetbackingstore.cpp b/Telegram/_qt_5_5_0_patch/qtbase/src/widgets/kernel/qwidgetbackingstore.cpp
new file mode 100644
index 000000000..1d2aff090
--- /dev/null
+++ b/Telegram/_qt_5_5_0_patch/qtbase/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -0,0 +1,1493 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qplatformdefs.h"
+
+#include "qwidgetbackingstore_p.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)
+# include
+# include
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern QRegion qt_dirtyRegion(QWidget *);
+
+/**
+ * Flushes the contents of the \a backingStore into the screen area of \a widget.
+ * \a tlwOffset is the position of the top level widget relative to the window surface.
+ * \a region is the region to be updated in \a widget coordinates.
+ */
+void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore,
+ QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures,
+ QWidgetBackingStore *widgetBackingStore)
+{
+#ifdef QT_NO_OPENGL
+ Q_UNUSED(widgetTextures);
+ Q_ASSERT(!region.isEmpty());
+#else
+ Q_ASSERT(!region.isEmpty() || (widgetTextures && widgetTextures->count()));
+#endif
+ Q_ASSERT(widget);
+ Q_ASSERT(backingStore);
+ Q_ASSERT(tlw);
+
+#if !defined(QT_NO_PAINT_DEBUG)
+ static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE");
+ if (flushUpdate > 0)
+ QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false);
+#endif
+
+ if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
+ return;
+ static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS");
+ if (fpsDebug) {
+ if (!widgetBackingStore->perfFrames++)
+ widgetBackingStore->perfTime.start();
+ if (widgetBackingStore->perfTime.elapsed() > 5000) {
+ double fps = double(widgetBackingStore->perfFrames * 1000) / widgetBackingStore->perfTime.restart();
+ qDebug("FPS: %.1f\n", fps);
+ widgetBackingStore->perfFrames = 0;
+ }
+ }
+
+ QPoint offset = tlwOffset;
+ if (widget != tlw)
+ offset += widget->mapTo(tlw, QPoint());
+
+#ifndef QT_NO_OPENGL
+ if (widgetTextures) {
+ widget->window()->d_func()->sendComposeStatus(widget->window(), false);
+ // A window may have alpha even when the app did not request
+ // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends
+ // to rely on translucency, in order to decide if it should clear to transparent or opaque.
+ const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground);
+ backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures,
+ widget->d_func()->shareContext(), translucentBackground);
+ widget->window()->d_func()->sendComposeStatus(widget->window(), true);
+ } else
+#endif
+ backingStore->flush(region, widget->windowHandle(), offset);
+}
+
+#ifndef QT_NO_PAINT_DEBUG
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec)
+{
+ // We expect to be passed a native parent.
+ QWindow *nativeWindow = widget->windowHandle();
+ if (!nativeWindow)
+ return;
+ void *hdcV = QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("getDC"), nativeWindow);
+ if (!hdcV)
+ return;
+ const HDC hdc = reinterpret_cast(hdcV);
+
+ HBRUSH brush;
+ static int i = 0;
+ switch (i) {
+ case 0:
+ brush = CreateSolidBrush(RGB(255, 255, 0));
+ break;
+ case 1:
+ brush = CreateSolidBrush(RGB(255, 200, 55));
+ break;
+ case 2:
+ brush = CreateSolidBrush(RGB(200, 255, 55));
+ break;
+ case 3:
+ brush = CreateSolidBrush(RGB(200, 200, 0));
+ break;
+ }
+ i = (i + 1) & 3;
+
+ foreach (const QRect &rect, region.rects()) {
+ RECT winRect;
+ SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom());
+ FillRect(hdc, &winRect, brush);
+ }
+ DeleteObject(brush);
+ QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow);
+ ::Sleep(msec);
+}
+#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped)
+{
+#ifdef Q_OS_WINRT
+ Q_UNUSED(msec)
+#endif
+ QRegion paintRegion = toBePainted;
+ QRect widgetRect = widget->rect();
+
+ if (!widget->internalWinId()) {
+ QWidget *nativeParent = widget->nativeParentWidget();
+ const QPoint offset = widget->mapTo(nativeParent, QPoint(0, 0));
+ paintRegion.translate(offset);
+ widgetRect.translate(offset);
+ widget = nativeParent;
+ }
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ Q_UNUSED(unclipped);
+ showYellowThing_win(widget, paintRegion, msec);
+#else
+ //flags to fool painter
+ bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped);
+ if (unclipped && !widget->d_func()->paintOnScreen())
+ widget->setAttribute(Qt::WA_PaintUnclipped);
+
+ const bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent);
+ if (setFlag)
+ widget->setAttribute(Qt::WA_WState_InPaintEvent);
+
+ //setup the engine
+ QPaintEngine *pe = widget->paintEngine();
+ if (pe) {
+ pe->setSystemClip(paintRegion);
+ {
+ QPainter p(widget);
+ p.setClipRegion(paintRegion);
+ static int i = 0;
+ switch (i) {
+ case 0:
+ p.fillRect(widgetRect, QColor(255,255,0));
+ break;
+ case 1:
+ p.fillRect(widgetRect, QColor(255,200,55));
+ break;
+ case 2:
+ p.fillRect(widgetRect, QColor(200,255,55));
+ break;
+ case 3:
+ p.fillRect(widgetRect, QColor(200,200,0));
+ break;
+ }
+ i = (i+1) & 3;
+ p.end();
+ }
+ }
+
+ if (setFlag)
+ widget->setAttribute(Qt::WA_WState_InPaintEvent, false);
+
+ //restore
+ widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped);
+
+ if (pe)
+ pe->setSystemClip(QRegion());
+
+#if defined(Q_OS_UNIX)
+ ::usleep(1000 * msec);
+#endif
+#endif // !Q_OS_WIN
+}
+
+bool QWidgetBackingStore::flushPaint(QWidget *widget, const QRegion &rgn)
+{
+ if (!widget)
+ return false;
+
+ int delay = 0;
+ if (widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
+ static int flushPaintEvent = qEnvironmentVariableIntValue("QT_FLUSH_PAINT_EVENT");
+ if (!flushPaintEvent)
+ return false;
+ delay = flushPaintEvent;
+ } else {
+ static int flushPaint = qEnvironmentVariableIntValue("QT_FLUSH_PAINT");
+ if (!flushPaint)
+ return false;
+ delay = flushPaint;
+ }
+
+ QWidgetBackingStore::showYellowThing(widget, rgn, delay * 10, true);
+ return true;
+}
+
+void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
+{
+ if (widget->d_func()->paintOnScreen() || rgn.isEmpty())
+ return;
+
+ QWidget *tlw = widget->window();
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (!tlwExtra)
+ return;
+
+ const QPoint offset = widget->mapTo(tlw, QPoint());
+ qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset, 0, tlw->d_func()->maybeBackingStore());
+}
+#endif // QT_NO_PAINT_DEBUG
+
+/*
+ Moves the whole rect by (dx, dy) in widget's coordinate system.
+ Doesn't generate any updates.
+*/
+bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)
+{
+ const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
+ const QRect tlwRect(QRect(pos, rect.size()));
+ if (fullUpdatePending || dirty.intersects(tlwRect))
+ return false; // We don't want to scroll junk.
+ return store->scroll(tlwRect, dx, dy);
+}
+
+void QWidgetBackingStore::releaseBuffer()
+{
+ if (store)
+ store->resize(QSize());
+}
+
+/*!
+ Prepares the window surface to paint a\ toClean region of the \a widget and
+ updates the BeginPaintInfo struct accordingly.
+
+ The \a toClean region might be clipped by the window surface.
+*/
+void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore,
+ BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates)
+{
+ Q_UNUSED(widget);
+ Q_UNUSED(toCleanIsInTopLevelCoordinates);
+
+ // Always flush repainted areas.
+ dirtyOnScreen += toClean;
+
+ backingStore->beforeBeginPaint(tlw->windowHandle());
+
+#ifdef QT_NO_PAINT_DEBUG
+ backingStore->beginPaint(toClean);
+#else
+ returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean);
+ // Avoid deadlock with QT_FLUSH_PAINT: the server will wait for
+ // the BackingStore lock, so if we hold that, the server will
+ // never release the Communication lock that we are waiting for in
+ // sendSynchronousCommand
+ if (!returnInfo->wasFlushed)
+ backingStore->beginPaint(toClean);
+#endif
+
+ Q_UNUSED(returnInfo);
+}
+
+void QWidgetBackingStore::endPaint(const QRegion &cleaned, QBackingStore *backingStore,
+ BeginPaintInfo *beginPaintInfo)
+{
+#ifndef QT_NO_PAINT_DEBUG
+ if (!beginPaintInfo->wasFlushed)
+ backingStore->endPaint();
+ else
+ QWidgetBackingStore::unflushPaint(tlw, cleaned);
+#else
+ Q_UNUSED(beginPaintInfo);
+ Q_UNUSED(cleaned);
+ backingStore->endPaint();
+#endif
+
+ backingStore->afterEndPaint(tlw->windowHandle());
+
+ flush();
+}
+
+/*!
+ Returns the region (in top-level coordinates) that needs repaint and/or flush.
+
+ If the widget is non-zero, only the dirty region for the widget is returned
+ and the region will be in widget coordinates.
+*/
+QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
+{
+ const bool widgetDirty = widget && widget != tlw;
+ const QRect tlwRect(topLevelRect());
+ const QRect surfaceGeometry(tlwRect.topLeft(), store->size());
+ if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
+ if (widgetDirty) {
+ const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
+ const QPoint offset(widget->mapTo(tlw, QPoint()));
+ const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset));
+ return dirtyWidgetRect.translated(-offset);
+ }
+ return QRect(QPoint(), tlwRect.size());
+ }
+
+ // Calculate the region that needs repaint.
+ QRegion r(dirty);
+ for (int i = 0; i < dirtyWidgets.size(); ++i) {
+ QWidget *w = dirtyWidgets.at(i);
+ if (widgetDirty && w != widget && !widget->isAncestorOf(w))
+ continue;
+ r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint()));
+ }
+
+ // Append the region that needs flush.
+ r += dirtyOnScreen;
+
+ if (dirtyOnScreenWidgets) { // Only in use with native child widgets.
+ for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
+ QWidget *w = dirtyOnScreenWidgets->at(i);
+ if (widgetDirty && w != widget && !widget->isAncestorOf(w))
+ continue;
+ QWidgetPrivate *wd = w->d_func();
+ Q_ASSERT(wd->needsFlush);
+ r += wd->needsFlush->translated(w->mapTo(tlw, QPoint()));
+ }
+ }
+
+ if (widgetDirty) {
+ // Intersect with the widget geometry and translate to its coordinates.
+ const QPoint offset(widget->mapTo(tlw, QPoint()));
+ r &= widget->rect().translated(offset);
+ r.translate(-offset);
+ }
+ return r;
+}
+
+/*!
+ Returns the static content inside the \a parent if non-zero; otherwise the static content
+ for the entire backing store is returned. The content will be clipped to \a withinClipRect
+ if non-empty.
+*/
+QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const
+{
+ if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) {
+ const QSize surfaceGeometry(store->size());
+ QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
+ if (!withinClipRect.isEmpty())
+ surfaceRect &= withinClipRect;
+ return QRegion(surfaceRect);
+ }
+
+ QRegion region;
+ if (parent && parent->d_func()->children.isEmpty())
+ return region;
+
+ const bool clipToRect = !withinClipRect.isEmpty();
+ const int count = staticWidgets.count();
+ for (int i = 0; i < count; ++i) {
+ QWidget *w = staticWidgets.at(i);
+ QWidgetPrivate *wd = w->d_func();
+ if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty()
+ || !w->isVisible() || (parent && !parent->isAncestorOf(w))) {
+ continue;
+ }
+
+ QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height());
+ const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint());
+ if (clipToRect)
+ rect &= withinClipRect.translated(-offset);
+ if (rect.isEmpty())
+ continue;
+
+ rect &= wd->clipRect();
+ if (rect.isEmpty())
+ continue;
+
+ QRegion visible(rect);
+ wd->clipToEffectiveMask(visible);
+ if (visible.isEmpty())
+ continue;
+ wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true);
+
+ visible.translate(offset);
+ region += visible;
+ }
+
+ return region;
+}
+
+void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime)
+{
+ if (!widget)
+ return;
+
+ switch (updateTime) {
+ case UpdateLater:
+ updateRequestSent = true;
+ QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
+ break;
+ case UpdateNow: {
+ QEvent event(QEvent::UpdateRequest);
+ QApplication::sendEvent(widget, &event);
+ break;
+ }
+ }
+}
+
+/*!
+ Marks the region of the widget as dirty (if not already marked as dirty) and
+ posts an UpdateRequest event to the top-level widget (if not already posted).
+
+ If updateTime is UpdateNow, the event is sent immediately instead of posted.
+
+ If bufferState is BufferInvalid, all widgets intersecting with the region will be dirty.
+
+ If the widget paints directly on screen, the event is sent to the widget
+ instead of the top-level widget, and bufferState is completely ignored.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,
+ UpdateTime updateTime, BufferState bufferState)
+{
+ Q_ASSERT(tlw->d_func()->extra);
+ Q_ASSERT(tlw->d_func()->extra->topextra);
+ Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
+ Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
+ Q_ASSERT(widget->window() == tlw);
+ Q_ASSERT(!rgn.isEmpty());
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ if (widget->d_func()->paintOnScreen()) {
+ if (widget->d_func()->dirty.isEmpty()) {
+ widget->d_func()->dirty = rgn;
+ sendUpdateRequest(widget, updateTime);
+ return;
+ } else if (qt_region_strictContains(widget->d_func()->dirty, widget->rect())) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(widget, updateTime);
+ return; // Already dirty.
+ }
+
+ const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
+ widget->d_func()->dirty += rgn;
+ if (!eventAlreadyPosted || updateTime == UpdateNow)
+ sendUpdateRequest(widget, updateTime);
+ return;
+ }
+
+ //### FIXME fullUpdatePending seems to be always false????
+ if (fullUpdatePending) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ const QPoint offset = widget->mapTo(tlw, QPoint());
+
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!widget->d_func()->inDirtyList)
+ addDirtyRenderToTextureWidget(widget);
+ if (!updateRequestSent || updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
+ if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return; // Already dirty.
+ }
+
+ if (bufferState == BufferInvalid) {
+ const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (widget->d_func()->graphicsEffect)
+ dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
+ else
+#endif //QT_NO_GRAPHICSEFFECT
+ dirty += rgn.translated(offset);
+ if (!eventAlreadyPosted || updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ if (dirtyWidgets.isEmpty()) {
+ addDirtyWidget(widget, rgn);
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ if (widget->d_func()->inDirtyList) {
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
+#ifndef QT_NO_GRAPHICSEFFECT
+ if (widget->d_func()->graphicsEffect)
+ widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect());
+ else
+#endif //QT_NO_GRAPHICSEFFECT
+ widget->d_func()->dirty += rgn;
+ }
+ } else {
+ addDirtyWidget(widget, rgn);
+ }
+
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+}
+
+/*!
+ This function is equivalent to calling markDirty(QRegion(rect), ...), but
+ is more efficient as it eliminates QRegion operations/allocations and can
+ use the rect more precisely for additional cut-offs.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
+ UpdateTime updateTime, BufferState bufferState)
+{
+ Q_ASSERT(tlw->d_func()->extra);
+ Q_ASSERT(tlw->d_func()->extra->topextra);
+ Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
+ Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
+ Q_ASSERT(widget->window() == tlw);
+ Q_ASSERT(!rect.isEmpty());
+
+#ifndef QT_NO_GRAPHICSEFFECT
+ widget->d_func()->invalidateGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
+
+ if (widget->d_func()->paintOnScreen()) {
+ if (widget->d_func()->dirty.isEmpty()) {
+ widget->d_func()->dirty = QRegion(rect);
+ sendUpdateRequest(widget, updateTime);
+ return;
+ } else if (qt_region_strictContains(widget->d_func()->dirty, rect)) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(widget, updateTime);
+ return; // Already dirty.
+ }
+
+ const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
+ widget->d_func()->dirty += rect;
+ if (!eventAlreadyPosted || updateTime == UpdateNow)
+ sendUpdateRequest(widget, updateTime);
+ return;
+ }
+
+ if (fullUpdatePending) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!widget->d_func()->inDirtyList)
+ addDirtyRenderToTextureWidget(widget);
+ if (!updateRequestSent || updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
+ const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
+ if (qt_region_strictContains(dirty, translatedRect)) {
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return; // Already dirty
+ }
+
+ if (bufferState == BufferInvalid) {
+ const bool eventAlreadyPosted = !dirty.isEmpty();
+ dirty += translatedRect;
+ if (!eventAlreadyPosted || updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ if (dirtyWidgets.isEmpty()) {
+ addDirtyWidget(widget, rect);
+ sendUpdateRequest(tlw, updateTime);
+ return;
+ }
+
+ if (widget->d_func()->inDirtyList) {
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect))
+ widget->d_func()->dirty += widgetRect;
+ } else {
+ addDirtyWidget(widget, rect);
+ }
+
+ if (updateTime == UpdateNow)
+ sendUpdateRequest(tlw, updateTime);
+}
+
+/*!
+ Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from
+ the backing store to the \a widget's native parent next time flush() is called.
+
+ Paint on screen widgets are ignored.
+*/
+void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widget, const QPoint &topLevelOffset)
+{
+ if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty())
+ return;
+
+#if defined(Q_DEAD_CODE_FROM_QT4_MAC)
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region.translated(topLevelOffset);
+ return;
+#endif
+
+ // Top-level.
+ if (widget == tlw) {
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region;
+ return;
+ }
+
+ // Alien widgets.
+ if (!widget->internalWinId() && !widget->isWindow()) {
+ QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
+ if (nativeParent == tlw) {
+ if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
+ dirtyOnScreen += region.translated(topLevelOffset);
+ return;
+ }
+
+ // Alien widgets with native parent != tlw.
+ QWidgetPrivate *nativeParentPrivate = nativeParent->d_func();
+ if (!nativeParentPrivate->needsFlush)
+ nativeParentPrivate->needsFlush = new QRegion;
+ const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint());
+ *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset);
+ appendDirtyOnScreenWidget(nativeParent);
+ return;
+ }
+
+ // Native child widgets.
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+ if (!widgetPrivate->needsFlush)
+ widgetPrivate->needsFlush = new QRegion;
+ *widgetPrivate->needsFlush += region;
+ appendDirtyOnScreenWidget(widget);
+}
+
+void QWidgetBackingStore::removeDirtyWidget(QWidget *w)
+{
+ if (!w)
+ return;
+
+ dirtyWidgetsRemoveAll(w);
+ dirtyOnScreenWidgetsRemoveAll(w);
+ dirtyRenderToTextureWidgets.removeAll(w);
+ resetWidget(w);
+
+ QWidgetPrivate *wd = w->d_func();
+ const int n = wd->children.count();
+ for (int i = 0; i < n; ++i) {
+ if (QWidget *child = qobject_cast(wd->children.at(i)))
+ removeDirtyWidget(child);
+ }
+}
+
+void QWidgetBackingStore::updateLists(QWidget *cur)
+{
+ if (!cur)
+ return;
+
+ QList children = cur->children();
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast(children.at(i));
+ if (!child)
+ continue;
+
+ updateLists(child);
+ }
+
+ if (cur->testAttribute(Qt::WA_StaticContents))
+ addStaticWidget(cur);
+}
+
+QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
+ : tlw(topLevel),
+ dirtyOnScreenWidgets(0),
+ widgetTextures(0),
+ fullUpdatePending(0),
+ updateRequestSent(0),
+ textureListWatcher(0),
+ perfFrames(0)
+{
+ store = tlw->backingStore();
+ Q_ASSERT(store);
+
+ // Ensure all existing subsurfaces and static widgets are added to their respective lists.
+ updateLists(topLevel);
+}
+
+QWidgetBackingStore::~QWidgetBackingStore()
+{
+ for (int c = 0; c < dirtyWidgets.size(); ++c)
+ resetWidget(dirtyWidgets.at(c));
+ for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c)
+ resetWidget(dirtyRenderToTextureWidgets.at(c));
+
+#ifndef QT_NO_OPENGL
+ delete widgetTextures;
+ delete dirtyOnScreenWidgets;
+#endif
+ dirtyOnScreenWidgets = 0;
+}
+
+//parent's coordinates; move whole rect; update parent and widget
+//assume the screen blt has already been done, so we don't need to refresh that part
+void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
+{
+ Q_Q(QWidget);
+ if (!q->isVisible() || (dx == 0 && dy == 0))
+ return;
+
+ QWidget *tlw = q->window();
+ QTLWExtra* x = tlw->d_func()->topData();
+ if (x->inTopLevelResize)
+ return;
+
+ static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_MOVE") == 0;
+
+ QWidget *pw = q->parentWidget();
+ QPoint toplevelOffset = pw->mapTo(tlw, QPoint());
+ QWidgetPrivate *pd = pw->d_func();
+ QRect clipR(pd->clipRect());
+ const QRect newRect(rect.translated(dx, dy));
+ QRect destRect = rect.intersected(clipR);
+ if (destRect.isValid())
+ destRect = destRect.translated(dx, dy).intersected(clipR);
+ const QRect sourceRect(destRect.translated(-dx, -dy));
+ const QRect parentRect(rect & clipR);
+
+ bool accelerateMove = accelEnv && isOpaque
+#ifndef QT_NO_GRAPHICSVIEW
+ // No accelerate move for proxy widgets.
+ && !tlw->d_func()->extra->proxyWidget
+#endif
+ && !isOverlapped(sourceRect) && !isOverlapped(destRect);
+
+ if (!accelerateMove) {
+ QRegion parentR(effectiveRectFor(parentRect));
+ if (!extra || !extra->hasMask) {
+ parentR -= newRect;
+ } else {
+ // invalidateBuffer() excludes anything outside the mask
+ parentR += newRect & clipR;
+ }
+ pd->invalidateBuffer(parentR);
+ invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
+ } else {
+
+ QWidgetBackingStore *wbs = x->backingStoreTracker.data();
+ QRegion childExpose(newRect & clipR);
+
+ if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw))
+ childExpose -= destRect;
+
+ if (!pw->updatesEnabled())
+ return;
+
+ const bool childUpdatesEnabled = q->updatesEnabled();
+ if (childUpdatesEnabled && !childExpose.isEmpty()) {
+ childExpose.translate(-data.crect.topLeft());
+ wbs->markDirty(childExpose, q);
+ isMoved = true;
+ }
+
+ QRegion parentExpose(parentRect);
+ parentExpose -= newRect;
+ if (extra && extra->hasMask)
+ parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft());
+
+ if (!parentExpose.isEmpty()) {
+ wbs->markDirty(parentExpose, pw);
+ pd->isMoved = true;
+ }
+
+ if (childUpdatesEnabled) {
+ QRegion needsFlush(sourceRect);
+ needsFlush += destRect;
+ wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset);
+ }
+ }
+}
+
+//widget's coordinates; scroll within rect; only update widget
+void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
+{
+ Q_Q(QWidget);
+ QWidget *tlw = q->window();
+ QTLWExtra* x = tlw->d_func()->topData();
+ if (x->inTopLevelResize)
+ return;
+
+ QWidgetBackingStore *wbs = x->backingStoreTracker.data();
+ if (!wbs)
+ return;
+
+ static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0;
+
+ QRect scrollRect = rect & clipRect();
+ bool overlapped = false;
+ bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent)
+ && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft())));
+
+ if (!accelerateScroll) {
+ if (overlapped) {
+ QRegion region(scrollRect);
+ subtractOpaqueSiblings(region);
+ invalidateBuffer(region);
+ }else {
+ invalidateBuffer(scrollRect);
+ }
+ } else {
+ const QPoint toplevelOffset = q->mapTo(tlw, QPoint());
+ const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;
+ const QRect sourceRect = destRect.translated(-dx, -dy);
+
+ QRegion childExpose(scrollRect);
+ if (sourceRect.isValid()) {
+ if (wbs->bltRect(sourceRect, dx, dy, q))
+ childExpose -= destRect;
+ }
+
+ if (inDirtyList) {
+ if (rect == q->rect()) {
+ dirty.translate(dx, dy);
+ } else {
+ QRegion dirtyScrollRegion = dirty.intersected(scrollRect);
+ if (!dirtyScrollRegion.isEmpty()) {
+ dirty -= dirtyScrollRegion;
+ dirtyScrollRegion.translate(dx, dy);
+ dirty += dirtyScrollRegion;
+ }
+ }
+ }
+
+ if (!q->updatesEnabled())
+ return;
+
+ if (!childExpose.isEmpty()) {
+ wbs->markDirty(childExpose, q);
+ isScrolled = true;
+ }
+
+ // Instead of using native scroll-on-screen, we copy from
+ // backingstore, giving only one screen update for each
+ // scroll, and a solid appearance
+ wbs->markDirtyOnScreen(destRect, q, toplevelOffset);
+ }
+}
+
+static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
+{
+ if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible())
+ return true;
+
+ return false;
+}
+
+/*!
+ Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store.
+
+ If there's nothing to repaint, the area is flushed and painting does not occur;
+ otherwise the area is marked as dirty on screen and will be flushed right after
+ we are done with all painting.
+*/
+void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion)
+{
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize)
+ return;
+
+ if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible() || !exposedWidget->testAttribute(Qt::WA_Mapped)
+ || !exposedWidget->updatesEnabled() || exposedRegion.isEmpty()) {
+ return;
+ }
+
+ // Nothing to repaint.
+ if (!isDirty() && store->size().isValid()) {
+ qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, this);
+ return;
+ }
+
+ if (exposedWidget != tlw)
+ markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint()));
+ else
+ markDirtyOnScreen(exposedRegion, exposedWidget, QPoint());
+
+ doSync();
+}
+
+#ifndef QT_NO_OPENGL
+static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures)
+{
+ QWidgetPrivate *wd = QWidgetPrivate::get(widget);
+ if (wd->renderToTexture) {
+ QPlatformTextureList::Flags flags = 0;
+ if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
+ flags |= QPlatformTextureList::StacksOnTop;
+ const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
+ widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
+ }
+
+ for (int i = 0; i < wd->children.size(); ++i) {
+ QWidget *w = qobject_cast(wd->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
+ findTextureWidgetsRecursively(tlw, w, widgetTextures);
+ }
+}
+
+QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)
+ : m_locked(false),
+ m_backingStore(backingStore)
+{
+}
+
+void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)
+{
+ connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));
+ m_locked = textureList->isLocked();
+}
+
+void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
+{
+ m_locked = locked;
+ if (!locked)
+ m_backingStore->sync();
+}
+#endif // QT_NO_OPENGL
+
+/*!
+ Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
+*/
+void QWidgetBackingStore::sync()
+{
+ updateRequestSent = false;
+ QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
+ if (discardSyncRequest(tlw, tlwExtra)) {
+ // If the top-level is minimized, it's not visible on the screen so we can delay the
+ // update until it's shown again. In order to do that we must keep the dirty states.
+ // These will be cleared when we receive the first expose after showNormal().
+ // However, if the widget is not visible (isVisible() returns false), everything will
+ // be invalidated once the widget is shown again, so clear all dirty states.
+ if (!tlw->isVisible()) {
+ dirty = QRegion();
+ for (int i = 0; i < dirtyWidgets.size(); ++i)
+ resetWidget(dirtyWidgets.at(i));
+ dirtyWidgets.clear();
+ fullUpdatePending = false;
+ }
+ return;
+ }
+
+#ifndef QT_NO_OPENGL
+ if (textureListWatcher && !textureListWatcher->isLocked()) {
+ textureListWatcher->deleteLater();
+ textureListWatcher = 0;
+ } else if (widgetTextures && widgetTextures->isLocked()) {
+ if (!textureListWatcher)
+ textureListWatcher = new QPlatformTextureListWatcher(this);
+ if (!textureListWatcher->isLocked())
+ textureListWatcher->watch(widgetTextures);
+ return;
+ }
+#endif
+
+ doSync();
+}
+
+void QWidgetBackingStore::doSync()
+{
+ const bool updatesDisabled = !tlw->updatesEnabled();
+ bool repaintAllWidgets = false;
+
+ const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize;
+ const QRect tlwRect(topLevelRect());
+ const QRect surfaceGeometry(tlwRect.topLeft(), store->size());
+ if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
+ if (hasStaticContents() && !store->size().isEmpty() ) {
+ // Repaint existing dirty area and newly visible area.
+ const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
+ const QRegion staticRegion(staticContents(0, clipRect));
+ QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
+ newVisible -= staticRegion;
+ dirty += newVisible;
+ store->setStaticContents(staticRegion);
+ } else {
+ // Repaint everything.
+ dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
+ for (int i = 0; i < dirtyWidgets.size(); ++i)
+ resetWidget(dirtyWidgets.at(i));
+ dirtyWidgets.clear();
+ repaintAllWidgets = true;
+ }
+ }
+
+ if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size())
+ store->resize(tlwRect.size());
+
+ if (updatesDisabled)
+ return;
+
+ // Contains everything that needs repaint.
+ QRegion toClean(dirty);
+
+ // Loop through all update() widgets and remove them from the list before they are
+ // painted (in case someone calls update() in paintEvent). If the widget is opaque
+ // and does not have transparent overlapping siblings, append it to the
+ // opaqueNonOverlappedWidgets list and paint it directly without composition.
+ QVarLengthArray opaqueNonOverlappedWidgets;
+ for (int i = 0; i < dirtyWidgets.size(); ++i) {
+ QWidget *w = dirtyWidgets.at(i);
+ QWidgetPrivate *wd = w->d_func();
+ if (wd->data.in_destructor)
+ continue;
+
+ // Clip with mask() and clipRect().
+ wd->dirty &= wd->clipRect();
+ wd->clipToEffectiveMask(wd->dirty);
+
+ // Subtract opaque siblings and children.
+ bool hasDirtySiblingsAbove = false;
+ // We know for sure that the widget isn't overlapped if 'isMoved' is true.
+ if (!wd->isMoved)
+ wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove);
+ // Scrolled and moved widgets must draw all children.
+ if (!wd->isScrolled && !wd->isMoved)
+ wd->subtractOpaqueChildren(wd->dirty, w->rect());
+
+ if (wd->dirty.isEmpty()) {
+ resetWidget(w);
+ continue;
+ }
+
+ const QRegion widgetDirty(w != tlw ? wd->dirty.translated(w->mapTo(tlw, QPoint()))
+ : wd->dirty);
+ toClean += widgetDirty;
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (tlw->d_func()->extra->proxyWidget) {
+ resetWidget(w);
+ continue;
+ }
+#endif
+
+ if (!hasDirtySiblingsAbove && wd->isOpaque && !dirty.intersects(widgetDirty.boundingRect())) {
+ opaqueNonOverlappedWidgets.append(w);
+ } else {
+ resetWidget(w);
+ dirty += widgetDirty;
+ }
+ }
+ dirtyWidgets.clear();
+
+#ifndef QT_NO_OPENGL
+ delete widgetTextures;
+ widgetTextures = 0;
+ if (tlw->d_func()->textureChildSeen) {
+ widgetTextures = new QPlatformTextureList;
+ findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
+ }
+ qt_window_private(tlw->windowHandle())->compositing = widgetTextures && !widgetTextures->isEmpty();
+ fullUpdatePending = false;
+#endif
+
+ if (toClean.isEmpty()) {
+ // Nothing to repaint. However renderToTexture widgets are handled
+ // specially, they are not in the regular dirty list, in order to
+ // prevent triggering unnecessary backingstore painting when only the
+ // OpenGL content changes. Check if we have such widgets in the special
+ // dirty list.
+ QVarLengthArray paintPending;
+ for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) {
+ QWidget *w = dirtyRenderToTextureWidgets.at(i);
+ paintPending << w;
+ resetWidget(w);
+ }
+ dirtyRenderToTextureWidgets.clear();
+ for (int i = 0; i < paintPending.count(); ++i) {
+ QWidget *w = paintPending[i];
+ w->d_func()->sendPaintEvent(w->rect());
+ }
+
+ // We might have newly exposed areas on the screen if this function was
+ // called from sync(QWidget *, QRegion)), so we have to make sure those
+ // are flushed. We also need to composite the renderToTexture widgets.
+ flush();
+
+ return;
+ }
+
+#ifndef QT_NO_OPENGL
+ if (widgetTextures && widgetTextures->count()) {
+ for (int i = 0; i < widgetTextures->count(); ++i) {
+ QWidget *w = static_cast(widgetTextures->source(i));
+ if (dirtyRenderToTextureWidgets.contains(w)) {
+ const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already
+ dirty += rect;
+ toClean += rect;
+ }
+ }
+ }
+ for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i)
+ resetWidget(dirtyRenderToTextureWidgets.at(i));
+ dirtyRenderToTextureWidgets.clear();
+#endif
+
+#ifndef QT_NO_GRAPHICSVIEW
+ if (tlw->d_func()->extra->proxyWidget) {
+ updateStaticContentsSize();
+ dirty = QRegion();
+ updateRequestSent = false;
+ const QVector rects(toClean.rects());
+ for (int i = 0; i < rects.size(); ++i)
+ tlw->d_func()->extra->proxyWidget->update(rects.at(i));
+ return;
+ }
+#endif
+
+ BeginPaintInfo beginPaintInfo;
+ beginPaint(toClean, tlw, store, &beginPaintInfo);
+ if (beginPaintInfo.nothingToPaint) {
+ for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
+ resetWidget(opaqueNonOverlappedWidgets[i]);
+ dirty = QRegion();
+ updateRequestSent = false;
+ return;
+ }
+
+ // Must do this before sending any paint events because
+ // the size may change in the paint event.
+ updateStaticContentsSize();
+ const QRegion dirtyCopy(dirty);
+ dirty = QRegion();
+ updateRequestSent = false;
+
+ // Paint opaque non overlapped widgets.
+ for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
+ QWidget *w = opaqueNonOverlappedWidgets[i];
+ QWidgetPrivate *wd = w->d_func();
+
+ int flags = QWidgetPrivate::DrawRecursive;
+ // Scrolled and moved widgets must draw all children.
+ if (!wd->isScrolled && !wd->isMoved)
+ flags |= QWidgetPrivate::DontDrawOpaqueChildren;
+ if (w == tlw)
+ flags |= QWidgetPrivate::DrawAsRoot;
+
+ QRegion toBePainted(wd->dirty);
+ resetWidget(w);
+
+ QPoint offset(tlwOffset);
+ if (w != tlw)
+ offset += w->mapTo(tlw, QPoint());
+ wd->drawWidget(store->paintDevice(), toBePainted, offset, flags, 0, this);
+ }
+
+ // Paint the rest with composition.
+ if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
+ const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
+ tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
+ }
+
+ endPaint(toClean, store, &beginPaintInfo);
+}
+
+/*!
+ Flushes the contents of the backing store into the top-level widget.
+ If the \a widget is non-zero, the content is flushed to the \a widget.
+ If the \a surface is non-zero, the content of the \a surface is flushed.
+*/
+void QWidgetBackingStore::flush(QWidget *widget)
+{
+ if (!dirtyOnScreen.isEmpty()) {
+ QWidget *target = widget ? widget : tlw;
+ qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this);
+ dirtyOnScreen = QRegion();
+#ifndef QT_NO_OPENGL
+ if (widgetTextures && widgetTextures->count())
+ return;
+#endif
+ }
+
+ if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
+#ifndef QT_NO_OPENGL
+ if (widgetTextures && widgetTextures->count()) {
+ QWidget *target = widget ? widget : tlw;
+ qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, this);
+ }
+#endif
+ return;
+ }
+
+ for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
+ QWidget *w = dirtyOnScreenWidgets->at(i);
+ QWidgetPrivate *wd = w->d_func();
+ Q_ASSERT(wd->needsFlush);
+ qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, 0, this);
+ *wd->needsFlush = QRegion();
+ }
+ dirtyOnScreenWidgets->clear();
+}
+
+static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
+{
+ Q_ASSERT(widget);
+ if (QApplication::closingDown())
+ return true;
+
+ if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
+ return true;
+
+ if (!widget->isVisible() || !widget->updatesEnabled())
+ return true;
+
+ return false;
+}
+
+/*!
+ Invalidates the buffer when the widget is resized.
+ Static areas are never invalidated unless absolutely needed.
+*/
+void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(!q->isWindow());
+ Q_ASSERT(q->parentWidget());
+
+ const bool staticContents = q->testAttribute(Qt::WA_StaticContents);
+ const bool sizeDecreased = (data.crect.width() < oldSize.width())
+ || (data.crect.height() < oldSize.height());
+
+ const QPoint offset(data.crect.x() - oldPos.x(), data.crect.y() - oldPos.y());
+ const bool parentAreaExposed = !offset.isNull() || sizeDecreased;
+ const QRect newWidgetRect(q->rect());
+ const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height());
+
+ if (!staticContents || graphicsEffect) {
+ QRegion staticChildren;
+ QWidgetBackingStore *bs = 0;
+ if (offset.isNull() && (bs = maybeBackingStore()))
+ staticChildren = bs->staticContents(q, oldWidgetRect);
+ const bool hasStaticChildren = !staticChildren.isEmpty();
+
+ if (hasStaticChildren) {
+ QRegion dirty(newWidgetRect);
+ dirty -= staticChildren;
+ invalidateBuffer(dirty);
+ } else {
+ // Entire widget needs repaint.
+ invalidateBuffer(newWidgetRect);
+ }
+
+ if (!parentAreaExposed)
+ return;
+
+ // Invalidate newly exposed area of the parent.
+ if (!graphicsEffect && extra && extra->hasMask) {
+ QRegion parentExpose(extra->mask.translated(oldPos));
+ parentExpose &= QRect(oldPos, oldSize);
+ if (hasStaticChildren)
+ parentExpose -= data.crect; // Offset is unchanged, safe to do this.
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ if (hasStaticChildren && !graphicsEffect) {
+ QRegion parentExpose(QRect(oldPos, oldSize));
+ parentExpose -= data.crect; // Offset is unchanged, safe to do this.
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
+ }
+ }
+ return;
+ }
+
+ // Move static content to its new position.
+ if (!offset.isNull()) {
+ if (sizeDecreased) {
+ const QSize minSize(qMin(oldSize.width(), data.crect.width()),
+ qMin(oldSize.height(), data.crect.height()));
+ moveRect(QRect(oldPos, minSize), offset.x(), offset.y());
+ } else {
+ moveRect(QRect(oldPos, oldSize), offset.x(), offset.y());
+ }
+ }
+
+ // Invalidate newly visible area of the widget.
+ if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {
+ QRegion newVisible(newWidgetRect);
+ newVisible -= oldWidgetRect;
+ invalidateBuffer(newVisible);
+ }
+
+ if (!parentAreaExposed)
+ return;
+
+ // Invalidate newly exposed area of the parent.
+ const QRect oldRect(oldPos, oldSize);
+ if (extra && extra->hasMask) {
+ QRegion parentExpose(oldRect);
+ parentExpose &= extra->mask.translated(oldPos);
+ parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ } else {
+ QRegion parentExpose(oldRect);
+ parentExpose -= data.crect;
+ q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ }
+}
+
+/*!
+ Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e.
+ all widgets intersecting with the region will be repainted when the backing store
+ is synced.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
+{
+ Q_Q(QWidget);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty())
+ return;
+
+ QRegion wrgn(rgn);
+ wrgn &= clipRect();
+ if (!graphicsEffect && extra && extra->hasMask)
+ wrgn &= extra->mask;
+ if (wrgn.isEmpty())
+ return;
+
+ tlwExtra->backingStoreTracker->markDirty(wrgn, q,
+ QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+}
+
+/*!
+ This function is equivalent to calling invalidateBuffer(QRegion(rect), ...), but
+ is more efficient as it eliminates QRegion operations/allocations and can
+ use the rect more precisely for additional cut-offs.
+
+ ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+*/
+void QWidgetPrivate::invalidateBuffer(const QRect &rect)
+{
+ Q_Q(QWidget);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ if (discardInvalidateBufferRequest(q, tlwExtra) || rect.isEmpty())
+ return;
+
+ QRect wRect(rect);
+ wRect &= clipRect();
+ if (wRect.isEmpty())
+ return;
+
+ if (graphicsEffect || !extra || !extra->hasMask) {
+ tlwExtra->backingStoreTracker->markDirty(wRect, q,
+ QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+ return;
+ }
+
+ QRegion wRgn(extra->mask);
+ wRgn &= wRect;
+ if (wRgn.isEmpty())
+ return;
+
+ tlwExtra->backingStoreTracker->markDirty(wRgn, q,
+ QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+}
+
+void QWidgetPrivate::repaint_sys(const QRegion &rgn)
+{
+ if (data.in_destructor)
+ return;
+
+ Q_Q(QWidget);
+ if (discardSyncRequest(q, maybeTopData()))
+ return;
+
+ if (q->testAttribute(Qt::WA_StaticContents)) {
+ if (!extra)
+ createExtra();
+ extra->staticContentsSize = data.crect.size();
+ }
+
+ QPaintEngine *engine = q->paintEngine();
+
+ // QGLWidget does not support partial updates if:
+ // 1) The context is double buffered
+ // 2) The context is single buffered and auto-fill background is enabled.
+ const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
+ || engine->type() == QPaintEngine::OpenGL2))
+ && (usesDoubleBufferedGLContext || q->autoFillBackground());
+ QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
+
+#ifdef Q_DEAD_CODE_FROM_QT4_MAC
+ // No difference between update() and repaint() on the Mac.
+ update_sys(toBePainted);
+ return;
+#endif
+
+ toBePainted &= clipRect();
+ clipToEffectiveMask(toBePainted);
+ if (toBePainted.isEmpty())
+ return; // Nothing to repaint.
+
+#ifndef QT_NO_PAINT_DEBUG
+ bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted);
+#endif
+
+ drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0);
+
+#ifndef QT_NO_PAINT_DEBUG
+ if (flushed)
+ QWidgetBackingStore::unflushPaint(q, toBePainted);
+#endif
+
+ if (q->paintingActive())
+ qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
+}
+
+
+QT_END_NAMESPACE