Compare commits

...

26 Commits

Author SHA1 Message Date
John Preston
20f1610d60 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-17 12:29:32 +03:00
John Preston
6dfa9dd3b5 langs updated, version 0.8.51 stable 2015-08-17 12:29:00 +03:00
John Preston
6a05924dcf version 0.8.51 prepared, with win7 and winxp fix 2015-08-16 19:37:56 +03:00
John Preston
2039cd4660 fixed win7 start 2015-08-16 18:27:34 +03:00
John Preston
8259314721 fixed crash in notifyShowNext(), not always enum pinned icons 2015-08-16 17:42:41 +03:00
John Preston
d32e476d96 version 0.8.50.dev fixed crash in Go to FAQ 2015-08-14 19:31:29 +03:00
John Preston
856502a06a Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:50:03 +03:00
John Preston
48ee79ed9d langs updated for 0.8.50.dev 2015-08-14 18:49:49 +03:00
John Preston
1897dad06b Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:48:18 +03:00
John Preston
a95822b2ec version 0.8.50.dev - fixes in Windows toast notifications support, fixes in linux input methods 2015-08-14 18:47:56 +03:00
John Preston
4cb22530ae Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:30:24 +03:00
John Preston
fa501b18e4 crashfix in sending audio files 2015-08-14 18:24:40 +03:00
John Preston
9002a49fcc added patch for fcitx input in linux 2015-08-13 18:26:38 +03:00
John Preston
6621171e60 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-13 18:11:18 +03:00
John Preston
c16ea77c52 altering AppUserModelId in pinned shortcut in Windows 2015-08-13 18:11:07 +03:00
John Preston
efa62ece72 added fcitx inputcontext plugin for linux version 2015-08-13 18:09:04 +03:00
telegramdesktop
869194f16a Merge pull request #819 from ner0x652/patch-1
Update README.md with a new supported OS
2015-08-13 15:36:10 +03:00
telegramdesktop
b5c4c34164 Merge pull request #843 from NgoHuy/ibus
Add Ibus supported by Qt5 officially
2015-08-13 15:23:21 +03:00
John Preston
30e96a1d5e improved translation, 0.8.49.dev 2015-08-12 21:09:03 +03:00
John Preston
82dc07ee42 fixed warnings, version 0.8.49.dev 2015-08-12 21:05:25 +03:00
John Preston
6a41d307bb Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-12 21:02:31 +03:00
John Preston
afac237f03 improved window activation in os x 2015-08-12 21:02:20 +03:00
John Preston
8511181508 version 0.8.49.dev - block/unblock users in profile, ask question and faq link in Settings, Windows 8/8.1/10 toast notifications 2015-08-12 21:01:32 +03:00
John Preston
cf9737e762 Windows 8/8.1/10 toast notifications support added 2015-08-11 22:50:48 +03:00
Severus
0647bbba0e Add Ibus symbol to Qt5 inputmethod 2015-06-21 10:20:56 +07:00
Cornel Punga
8e1c10463f Update README.md with a new supported OS
It also work on Fedora 22. Tested!
2015-06-11 12:34:35 +03:00
102 changed files with 24189 additions and 676 deletions

View File

@@ -76,6 +76,16 @@ then go to **/home/user/TBuild/Libraries/openal-soft/build** and run
make
sudo make install
####libxkbcommon (required for Fcitx Qt plugin)
In Terminal go to **/home/user/TBuild/Libraries** and run
sudo apt-get install xutils-dev bison python-xcbgen
git clone https://github.com/xkbcommon/libxkbcommon.git
./autogen.sh --disable-x11
make
sudo make install
####Qt 5.5.0, slightly patched
http://download.qt-project.org/official_releases/qt/5.5/5.5.0/single/qt-everywhere-opensource-src-5.5.0.tar.gz

View File

@@ -6,10 +6,11 @@ Source code is published under GPL v3, license is available [here](https://githu
###Supported systems
* Windows XP - Windows 8.1 (**not** RT)
* Windows XP - Windows 10 (**not** RT)
* Mac OS X 10.8 - Mac OS X 10.10
* Mac OS X 10.6 - Mac OS X 10.7 (separate build)
* Ubuntu 12.04 - Ubuntu 14.04
* Fedora 22
###Third-party

View File

@@ -1,10 +1,10 @@
@echo OFF
set "AppVersionStrMajor=0.8"
set "AppVersion=8048"
set "AppVersionStrSmall=0.8.48"
set "AppVersionStr=0.8.48"
set "AppVersionStrFull=0.8.48.0"
set "AppVersion=8051"
set "AppVersionStrSmall=0.8.51"
set "AppVersionStr=0.8.51"
set "AppVersionStrFull=0.8.51.0"
set "DevChannel=0"
if %DevChannel% neq 0 goto preparedev

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Try now";
"lng_status_service_notifications" = "service notifications";
"lng_status_support" = "support";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "has access to messages";
"lng_status_bot_not_reads_all" = "has no access to messages";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Desktop notifications";
"lng_settings_show_name" = "Show sender's name";
"lng_settings_show_preview" = "Show message preview";
"lng_settings_use_windows" = "Use Windows notifications";
"lng_settings_sound_notify" = "Play sound";
"lng_notification_preview" = "You have a new message";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Do you want to terminate this session?";
"lng_settings_reset_button" = "Terminate";
"lng_settings_reset_done" = "Other sessions terminated";
"lng_settings_ask_question" = "Ask a Question";
"lng_settings_ask_sure" = "Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions.";
"lng_settings_faq_button" = "Go to FAQ";
"lng_settings_ask_ok" = "Ask";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_logout" = "Log Out";
"lng_sure_logout" = "Are you sure you want to log out?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "Delete conversation";
"lng_profile_clear_and_exit" = "Delete and exit";
"lng_profile_search_messages" = "Search for messages";
"lng_profile_block_user" = "Block user";
"lng_profile_unblock_user" = "Unblock user";
"lng_profile_block_bot" = "Stop and block bot";
"lng_profile_unblock_bot" = "Unblock bot";
"lng_profile_send_message" = "Send Message";
"lng_profile_share_contact" = "Share Contact";
"lng_profile_invite_to_group" = "Add to Group";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "You";
"lng_bot_description" = "What can this bot do?";
"lng_unblock_button" = "Unblock";
"lng_bot_start" = "Start";
"lng_bot_choose_group" = "Choose Group";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
"lng_new_version_text" = "— Search for messages in conversation\n— Clear messages history in groups\n— Contacts without messages are hidden from the conversations list";
"lng_new_version_text" = "— Block users from their profile page\n— Added support for Windows toast notifications\n— Fixed input methods on Linux (Fcitx and IBus)";
"lng_menu_insert_unicode" = "Insert Unicode control character";

View File

@@ -972,6 +972,11 @@ btnSend: flatButton(btnDefFlat) {
font: font(16px);
overFont: font(16px);
}
btnUnblock: flatButton(btnSend) {
color: #d15948;
overColor: #d15948;
downColor: #db6352;
}
btnAttachDocument: iconedButton(btnDefIconed) {
icon: sprite(218px, 68px, 24px, 24px);

View File

@@ -199,6 +199,7 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result) {
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
peer->asUser()->setBotInfo(d.vbot_info);
peer->asUser()->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
_fullPeerRequests.remove(peer);
App::clearPeerUpdated(peer);

View File

@@ -289,8 +289,10 @@ namespace App {
}
QString onlineText(UserData *user, int32 now, bool precise) {
if (isServiceUser(user->id)) {
if (isNotificationsUser(user->id)) {
return lang(lng_status_service_notifications);
} else if (isServiceUser(user->id)) {
return lang(lng_status_support);
} else if (user->botInfo) {
return lang(lng_status_bot);
}
@@ -370,8 +372,8 @@ namespace App {
PeerId peer(peerFromUser(d.vid.v));
data = App::user(peer);
data->input = MTP_inputPeerContact(d.vid);
data->inputUser = MTP_inputUserContact(d.vid);
data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
data->setName(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess;
@@ -389,12 +391,12 @@ namespace App {
if (flags & MTPDuser_flag_self) {
data->input = MTP_inputPeerSelf();
data->inputUser = MTP_inputUserSelf();
} else if ((flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) || !d.has_access_hash()) {
data->input = MTP_inputPeerContact(d.vid);
data->inputUser = MTP_inputUserContact(d.vid);
} else if (!d.has_access_hash()) {
data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
} else {
data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash);
data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash);
}
if (flags & MTPDuser_flag_deleted) {
data->setPhone(QString());
@@ -868,14 +870,8 @@ namespace App {
if (user->contact > 0) {
if (!wasContact) {
App::main()->addNewContact(App::userFromPeer(user->id), false);
if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerContact(userId);
if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserContact(userId);
}
} else {
if (user->access && user->access != UserNoAccess) {
if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerForeign(userId, MTP_long(user->access));
if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserForeign(userId, MTP_long(user->access));
}
if (user->contact < 0 && !user->phone.isEmpty() && App::userFromPeer(user->id) != MTP::authedId()) {
user->contact = 0;
}
@@ -924,7 +920,7 @@ namespace App {
return feedPhoto(photo.c_photo(), convert);
} break;
case mtpc_photoEmpty: {
return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
} break;
}
return App::photo(0);
@@ -968,7 +964,7 @@ namespace App {
switch (photo.type()) {
case mtpc_photo: {
const MTPDphoto &ph(photo.c_photo());
return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vuser_id.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
} break;
case mtpc_photoEmpty: return App::photo(photo.c_photoEmpty().vid.v);
}
@@ -1023,13 +1019,13 @@ namespace App {
}
}
if (thumb && medium && full) {
return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vuser_id.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
}
return App::photoSet(photo.vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
return App::photoSet(photo.vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
}
VideoData *feedVideo(const MTPDvideo &video, VideoData *convert) {
return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vuser_id.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
}
AudioData *feedAudio(const MTPaudio &audio, AudioData *convert) {
@@ -1038,14 +1034,14 @@ namespace App {
return feedAudio(audio.c_audio(), convert);
} break;
case mtpc_audioEmpty: {
return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, 0, QString(), 0, 0, 0);
return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, QString(), 0, 0, 0);
} break;
}
return App::audio(0);
}
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) {
return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
}
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) {
@@ -1172,7 +1168,7 @@ namespace App {
return i.value();
}
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
if (convert) {
if (convert->id != photo) {
PhotosData::iterator i = photosData.find(convert->id);
@@ -1182,8 +1178,7 @@ namespace App {
convert->id = photo;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->thumb = thumb;
convert->medium = medium;
@@ -1197,14 +1192,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new PhotoData(photo, access, user, date, thumb, medium, full);
result = new PhotoData(photo, access, date, thumb, medium, full);
}
photosData.insert(photo, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->thumb = thumb;
result->medium = medium;
@@ -1234,7 +1228,7 @@ namespace App {
return i.value();
}
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
if (convert) {
if (convert->id != video) {
VideosData::iterator i = videosData.find(convert->id);
@@ -1245,8 +1239,7 @@ namespace App {
convert->status = FileReady;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->duration = duration;
convert->w = w;
@@ -1262,14 +1255,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new VideoData(video, access, user, date, duration, w, h, thumb, dc, size);
result = new VideoData(video, access, date, duration, w, h, thumb, dc, size);
}
videosData.insert(video, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->duration = duration;
result->w = w;
@@ -1290,7 +1282,7 @@ namespace App {
return i.value();
}
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
if (convert) {
if (convert->id != audio) {
AudiosData::iterator i = audiosData.find(convert->id);
@@ -1301,8 +1293,7 @@ namespace App {
convert->status = FileReady;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->mime = mime;
convert->duration = duration;
@@ -1316,14 +1307,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new AudioData(audio, access, user, date, mime, duration, dc, size);
result = new AudioData(audio, access, date, mime, duration, dc, size);
}
audiosData.insert(audio, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->mime = mime;
result->duration = duration;
@@ -1547,7 +1537,7 @@ namespace App {
photoSizes.push_back(MTP_photoSize(MTP_string("a"), uphoto.vphoto_small, MTP_int(160), MTP_int(160), MTP_int(0)));
photoSizes.push_back(MTP_photoSize(MTP_string("c"), uphoto.vphoto_big, MTP_int(640), MTP_int(640), MTP_int(0)));
return MTP_photo(uphoto.vphoto_id, MTP_long(0), userId, date, MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
return MTP_photo(uphoto.vphoto_id, MTP_long(0), date, MTP_vector<MTPPhotoSize>(photoSizes));
}
return MTP_photoEmpty(MTP_long(0));
}

View File

@@ -158,11 +158,11 @@ namespace App {
ChatData *chat(int32 chat);
QString peerName(const PeerData *peer, bool forDialogs = false);
PhotoData *photo(const PhotoId &photo);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
VideoData *video(const VideoId &video);
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
AudioData *audio(const AudioId &audio);
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
DocumentData *document(const DocumentId &document);
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
WebPageData *webPage(const WebPageId &webPage);

View File

@@ -110,7 +110,6 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv),
}
mainApp = this;
installEventFilter(new EventFilterForKeys(this));
QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Regular.ttf"));
@@ -474,7 +473,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId)
PhotoId id = MTP::nonce<PhotoId>();
MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(MTP::authedId()), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes)));
MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes)));
QString file, filename;
int32 filesize = 0;
@@ -655,12 +654,11 @@ void Application::socketError(QLocalSocket::LocalSocketError e) {
void Application::checkMapVersion() {
if (Local::oldMapVersion() < AppVersion) {
psRegisterCustomScheme();
if (Local::oldMapVersion()) {
QString versionFeatures;
if (cDevVersion() && Local::oldMapVersion() < 8047) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Search for messages in conversation\n\xe2\x80\x94 Clear messages history in groups\n\xe2\x80\x94 Contacts without messages are hidden from the conversations list");// .replace('@', qsl("@") + QChar(0x200D));
} else if (!cDevVersion() && Local::oldMapVersion() < 8048) {
if (cDevVersion() && Local::oldMapVersion() < 8050) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Bug fixes in Windows notifications\n\xe2\x80\x94 Fixed input methods on Linux (Fcitx and IBus)");// .replace('@', qsl("@") + QChar(0x200D));
} else if (!cDevVersion() && Local::oldMapVersion() < 8051) {
versionFeatures = lang(lng_new_version_text).trimmed();
}
if (!versionFeatures.isEmpty()) {

View File

@@ -1099,7 +1099,11 @@ public:
}
freq = fmtContext->streams[streamId]->codec->sample_rate;
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
len = (fmtContext->duration * freq) / AV_TIME_BASE;
} else {
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
}
uint64_t layout = fmtContext->streams[streamId]->codec->channel_layout;
inputFormat = fmtContext->streams[streamId]->codec->sample_fmt;
switch (layout) {
@@ -2221,7 +2225,9 @@ public:
int res = 0;
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) {
DEBUG_LOG(("Audio Read Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
ioBuffer = 0;
DEBUG_LOG(("Audio Read Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false;
}
_opened = true;
@@ -2244,7 +2250,11 @@ public:
}
freq = fmtContext->streams[streamId]->codec->sample_rate;
len = (fmtContext->streams[streamId]->duration * freq) / fmtContext->streams[streamId]->time_base.den;
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
len = (fmtContext->duration * freq) / AV_TIME_BASE;
} else {
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
}
for (int32 i = 0, l = fmtContext->nb_streams; i < l; ++i) {
AVStream *stream = fmtContext->streams[i];

View File

@@ -56,19 +56,24 @@ void ConfirmBox::init(const QString &text) {
_confirm.hide();
_cancel.hide();
connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel()));
setMouseTracking(_text.hasLinks());
} else {
_close.hide();
connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
}
prepare();
}
void ConfirmBox::onCancel() {
emit cancelPressed();
onClose();
}
void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos();
updateHover();

View File

@@ -35,10 +35,15 @@ public:
void leaveEvent(QEvent *e);
void updateLink();
public slots:
void onCancel();
signals:
void confirmed();
void cancelled();
void cancelPressed();
protected:

View File

@@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
static const int32 AppVersion = 8048;
static const wchar_t *AppVersionStr = L"0.8.48";
static const int32 AppVersion = 8051;
static const wchar_t *AppVersionStr = L"0.8.51";
static const bool DevVersion = false;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
@@ -144,10 +144,14 @@ enum {
ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file
};
inline bool isServiceUser(uint64 id) {
inline bool isNotificationsUser(uint64 id) {
return (id == 333000) || (id == ServiceUserId);
}
inline bool isServiceUser(uint64 id) {
return !(id % 1000);// (id == 333000) || (id == ServiceUserId);
}
#ifdef Q_OS_WIN
inline const GUID &cGUID() {
static const GUID gGuid = { 0x87a94ab0, 0xe370, 0x4cde, { 0x98, 0xd3, 0xac, 0xc1, 0x10, 0xc5, 0x96, 0x7d } };
@@ -291,7 +295,7 @@ enum {
DefaultChatBackground = 21,
DialogsFirstLoad = 20, // first dialogs part size requested
DialogsPerPage = 40, // next dialogs part size
DialogsPerPage = 200, // next dialogs part size
MessagesFirstLoad = 30, // first history part size requested
MessagesPerPage = 50, // next history part size
@@ -321,6 +325,7 @@ enum {
MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory
NotifyWindowsCount = 3, // 3 desktop notifies at the same time
NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server
NotifyDeletePhotoAfter = 60000, // delete notify photo after 1 minute
UpdateChunk = 100 * 1024, // 100kb parts when downloading the update
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle

View File

@@ -969,7 +969,7 @@ void DialogsListWidget::selectSkip(int32 direction) {
if (!sel) {
if (dialogs.list.count && direction > 0) {
sel = dialogs.list.begin;
} else if (contactsNoDialogs.list.count && direction > 0) {
} else if (false && contactsNoDialogs.list.count && direction > 0) {
sel = contactsNoDialogs.list.begin;
} else {
return;
@@ -977,14 +977,14 @@ void DialogsListWidget::selectSkip(int32 direction) {
} else if (direction > 0) {
if (sel->next->next) {
sel = sel->next;
} else if (sel->next == dialogs.list.end && contactsNoDialogs.list.count) {
} else if (false && sel->next == dialogs.list.end && contactsNoDialogs.list.count) {
sel = contactsNoDialogs.list.begin;
contactSel = true;
}
} else {
if (sel->prev) {
sel = sel->prev;
} else if (sel == contactsNoDialogs.list.begin && dialogs.list.count) {
} else if (false && sel == contactsNoDialogs.list.begin && dialogs.list.count) {
sel = dialogs.list.end->prev;
contactSel = false;
}
@@ -1042,7 +1042,7 @@ void DialogsListWidget::scrollToPeer(const PeerId &peer, MsgId msgId) {
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(peer);
if (i != dialogs.list.rowByPeer.cend()) {
fromY = i.value()->pos * st::dlgHeight;
} else {
} else if (false) {
i = contactsNoDialogs.list.rowByPeer.constFind(peer);
if (i != contactsNoDialogs.list.rowByPeer.cend()) {
fromY = (i.value()->pos + dialogs.list.count) * st::dlgHeight;
@@ -1077,7 +1077,7 @@ void DialogsListWidget::selectSkipPage(int32 pixels, int32 direction) {
if (!sel) {
if (direction > 0 && dialogs.list.count) {
sel = dialogs.list.begin;
} else if (direction > 0 && contactsNoDialogs.list.count) {
} else if (false && direction > 0 && contactsNoDialogs.list.count) {
sel = contactsNoDialogs.list.begin;
} else {
return;
@@ -1087,7 +1087,7 @@ void DialogsListWidget::selectSkipPage(int32 pixels, int32 direction) {
while (toSkip-- && sel->next->next) {
sel = sel->next;
}
if (toSkip >= 0 && sel->next == dialogs.list.end && contactsNoDialogs.list.count) {
if (false && toSkip >= 0 && sel->next == dialogs.list.end && contactsNoDialogs.list.count) {
sel = contactsNoDialogs.list.begin;
while (toSkip-- && sel->next->next) {
sel = sel->next;
@@ -1358,17 +1358,17 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData
if (_state == DefaultState) {
DialogsList::RowByPeer::const_iterator i = dialogs.list.rowByPeer.constFind(inPeer->id);
if (i == dialogs.list.rowByPeer.constEnd()) {
i = contactsNoDialogs.list.rowByPeer.constFind(inPeer->id);
if (i == contactsNoDialogs.list.rowByPeer.cend()) {
outPeer = 0;
outMsg = 0;
return;
}
if (i.value()->next != contactsNoDialogs.list.end) {
outPeer = i.value()->next->history->peer;
outMsg = ShowAtUnreadMsgId;
return;
}
//i = contactsNoDialogs.list.rowByPeer.constFind(inPeer->id);
//if (i == contactsNoDialogs.list.rowByPeer.cend()) {
// outPeer = 0;
// outMsg = 0;
// return;
//}
//if (i.value()->next != contactsNoDialogs.list.end) {
// outPeer = i.value()->next->history->peer;
// outMsg = ShowAtUnreadMsgId;
// return;
//}
outPeer = 0;
outMsg = 0;
return;
@@ -1378,7 +1378,7 @@ void DialogsListWidget::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData
outPeer = i.value()->next->history->peer;
outMsg = ShowAtUnreadMsgId;
return;
} else if (contactsNoDialogs.list.count) {
} else if (false && contactsNoDialogs.list.count) {
outPeer = contactsNoDialogs.list.begin->history->peer;
outMsg = ShowAtUnreadMsgId;
return;

View File

@@ -154,6 +154,10 @@ inline StorageKey storageKey(int32 dc, const uint64 &volume, int32 local) {
inline StorageKey storageKey(const MTPDfileLocation &location) {
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
}
inline StorageKey storageKey(const StorageImageLocation &location) {
return storageKey(location.dc, location.volume, location.local);
}
enum StorageFileType {
StorageFileUnknown = 0xaa963b05, // mtpc_storage_fileUnknown
StorageFileJpeg = 0x7efe0e, // mtpc_storage_fileJpeg

View File

@@ -75,7 +75,9 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo
_trippleClickTimer.setSingleShot(true);
if (botInfo && !botInfo->inited) App::api()->requestFullPeer(hist->peer);
if (botInfo && !botInfo->inited) {
App::api()->requestFullPeer(hist->peer);
}
setMouseTracking(true);
}
@@ -2200,7 +2202,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _toHistoryEnd(this, st::historyToEnd)
, _attachMention(this)
, _send(this, lang(lng_send_button), st::btnSend)
, _unblock(this, lang(lng_unblock_button), st::btnUnblock)
, _botStart(this, lang(lng_bot_start), st::btnSend)
, _unblockRequest(0)
, _attachDocument(this, st::btnAttachDocument)
, _attachPhoto(this, st::btnAttachPhoto)
, _attachEmoji(this, st::btnAttachEmoji)
@@ -2243,6 +2247,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel()));
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
@@ -2305,6 +2310,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_field.hide();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width(), _send.height() - 2 * st::sendPadding);
_send.hide();
_unblock.hide();
_botStart.hide();
_attachDocument.hide();
@@ -2368,8 +2374,8 @@ void HistoryWidget::onTextChange() {
}
if (updateCmdStartShown()) {
updateControlsVisibility();
resizeEvent(0);
update();
resizeEvent(0);
update();
}
if (!_history || _synthedTextUpdate) return;
@@ -2482,7 +2488,7 @@ void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
void HistoryWidget::activate() {
if (_history) updateListSize(0, true);
if (_list) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
_list->setFocus();
} else {
_field.setFocus();
@@ -2776,6 +2782,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
}
_peer = peerId ? App::peer(peerId) : 0;
_unblockRequest = 0;
_titlePeerText = QString();
_titlePeerTextWidth = 0;
@@ -2890,6 +2897,7 @@ void HistoryWidget::updateControlsVisibility() {
_scroll.hide();
_kbScroll.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
_attachMention.hide();
_field.hide();
@@ -2914,7 +2922,25 @@ void HistoryWidget::updateControlsVisibility() {
}
if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
checkMentionDropdown();
if (isBotStart()) {
if (isBlocked()) {
_botStart.hide();
if (_unblock.isHidden()) {
_unblock.clearState();
_unblock.show();
_kbShown = false;
}
_send.hide();
_field.hide();
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
} else if (isBotStart()) {
_unblock.hide();
if (_botStart.isHidden()) {
_botStart.clearState();
_botStart.show();
@@ -2931,6 +2957,7 @@ void HistoryWidget::updateControlsVisibility() {
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
} else {
_unblock.hide();
_botStart.hide();
if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
_send.hide();
@@ -3007,6 +3034,7 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_attachMention.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
@@ -3321,6 +3349,29 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
if (!_keyboard.hasMarkup() && _keyboard.forceReply() && !_kbReplyTo) onKbToggle();
}
void HistoryWidget::onUnblock() {
if (_unblockRequest) return;
if (!_peer || _peer->chat || _peer->asUser()->blocked != UserIsBlocked) {
updateControlsVisibility();
return;
}
_unblockRequest = MTP::send(MTPcontacts_Unblock(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::unblockDone, _peer), rpcFail(&HistoryWidget::unblockFail));
}
void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result) {
if (peer->chat) return;
_unblockRequest = 0;
peer->asUser()->blocked = UserIsNotBlocked;
emit App::main()->peerUpdated(peer);
}
bool HistoryWidget::unblockFail(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
// _unblockRequest = 0;
return false;
}
void HistoryWidget::onBotStart() {
if (!_peer || _peer->chat || !_peer->asUser()->botInfo) {
updateControlsVisibility();
@@ -3374,7 +3425,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
flags |= MTPDmessage::flag_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup, MTPnullEntities));
h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, h->sendRequestId);
App::historyRegRandom(randomId, newId);
@@ -3418,6 +3469,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
_field.hide();
_replyForwardPreviewCancel.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
a_alpha = anim::fvalue(0, 1);
@@ -3470,7 +3522,7 @@ void HistoryWidget::animStop() {
bool HistoryWidget::recordStep(float64 ms) {
float64 dt = ms / st::btnSend.duration;
bool res = true;
if (dt >= 1 || !_send.isHidden() || isBotStart()) {
if (dt >= 1 || !_send.isHidden() || isBotStart() || isBlocked()) {
res = false;
a_recordOver.finish();
a_recordDown.finish();
@@ -3787,10 +3839,14 @@ bool HistoryWidget::isBotStart() const {
return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg);
}
bool HistoryWidget::isBlocked() const {
return _peer && !_peer->chat && _peer->asUser()->blocked == UserIsBlocked;
}
bool HistoryWidget::updateCmdStartShown() {
bool cmdStartShown = false;
if (_history && _peer && ((_peer->chat && _peer->asChat()->botStatus > 0) || (!_peer->chat && _peer->asUser()->botInfo))) {
if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (!isBotStart() && !isBlocked() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (_field.getLastText().isEmpty()) {
cmdStartShown = true;
}
@@ -4069,6 +4125,7 @@ void HistoryWidget::onFieldResize() {
_attachDocument.move(0, height() - kbh - _attachDocument.height());
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_send.move(width() - _send.width(), _attachDocument.y());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
@@ -4242,11 +4299,11 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
int32 flags = newMessageFlags(h->peer); // unread, out
if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id;
if (img.type == ToPreparePhoto) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareDocument) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareAudio) {
h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities));
}
if (_peer && img.peer == _peer->id) {
@@ -4427,7 +4484,7 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) {
if (_peer && _list && peer == _peer->id) {
updateListSize();
updateBotKeyboard();
if (!_scroll.isHidden() && _botStart.isHidden() == isBotStart()) {
if (!_scroll.isHidden() && !isBlocked() && _botStart.isHidden() == isBotStart()) {
updateControlsVisibility();
resizeEvent(0);
}
@@ -4468,6 +4525,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_send.move(width() - _send.width(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
_kbHide.move(_attachEmoji.x(), _attachEmoji.y());
@@ -4537,7 +4595,9 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
}
int32 newScrollHeight = height();
if (isBotStart()) {
if (isBlocked()) {
newScrollHeight -= _unblock.height();
} else if (isBotStart()) {
newScrollHeight -= _botStart.height();
} else {
if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
@@ -4676,7 +4736,7 @@ void HistoryWidget::updateBotKeyboard() {
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
if (hasMarkup || forceReply) {
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) _kbWasHidden = true;
if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!_showAnim.animating()) {
if (hasMarkup) {
_kbScroll.show();
@@ -5094,6 +5154,9 @@ void HistoryWidget::onFullPeerUpdated(PeerData *data) {
updateControlsVisibility();
resizeEvent(0);
update();
} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
updateControlsVisibility();
resizeEvent(0);
}
if (newScrollTop != _scroll.scrollTop()) {
if (_scroll.isVisible()) {
@@ -5110,6 +5173,11 @@ void HistoryWidget::peerUpdated(PeerData *data) {
if (!_showAnim.animating()) updateControlsVisibility();
if (data->chat && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) {
App::api()->requestFullPeer(data);
} else if (!data->chat && data->asUser()->blocked == UserBlockUnknown) {
App::api()->requestFullPeer(data);
} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
updateControlsVisibility();
resizeEvent(0);
}
App::main()->updateOnlineDisplay();
}
@@ -5225,7 +5293,7 @@ void HistoryWidget::updateTopBarSelection() {
updateControlsVisibility();
updateListSize();
if (!App::wnd()->layerShown() && !App::passcoded()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
_list->setFocus();
} else {
_field.setFocus();

View File

@@ -518,6 +518,7 @@ public slots:
void onListScroll();
void onHistoryToEnd();
void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
void onUnblock();
void onBotStart();
void onPhotoSelect();
@@ -604,6 +605,9 @@ private:
void addMessagesToFront(const QVector<MTPMessage> &messages);
void addMessagesToBack(const QVector<MTPMessage> &messages);
void unblockDone(PeerData *peer, const MTPBool &result);
bool unblockFail(const RPCError &error);
void countHistoryShowFrom();
void updateToEndVisibility();
@@ -640,9 +644,11 @@ private:
MentionsDropdown _attachMention;
bool isBotStart() const;
bool isBlocked() const;
bool updateCmdStartShown();
FlatButton _send, _botStart;
FlatButton _send, _unblock, _botStart;
mtpRequestId _unblockRequest;
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
bool _cmdStartShown;
MessageField _field;

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Jetzt versuchen";
"lng_status_service_notifications" = "Servicemeldungen";
"lng_status_support" = "Support";
"lng_status_bot" = "Bot";
"lng_status_bot_reads_all" = "hat Zugriff auf Nachrichten";
"lng_status_bot_not_reads_all" = "hat keinen Zugriff auf Nachrichten";
@@ -183,8 +184,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_section_notify" = "Benachrichtigungen";
"lng_settings_desktop_notify" = "Desktopbenachrichtigungen";
"lng_settings_show_name" = "Sendername anzeigen";
"lng_settings_show_name" = "Absendername anzeigen";
"lng_settings_show_preview" = "Nachrichtenvorschau anzeigen";
"lng_settings_use_windows" = "Windows Benachrichtigungen";
"lng_settings_sound_notify" = "Ton abspielen";
"lng_notification_preview" = "Du hast eine neue Nachricht";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Dieses Gerät wirklich abmelden?";
"lng_settings_reset_button" = "Beenden";
"lng_settings_reset_done" = "Alle anderen Sitzungen wurden erfolgreich beendet.";
"lng_settings_ask_question" = "Eine Frage stellen";
"lng_settings_ask_sure" = "Bedenke bitte, dass der Telegram Support von ehrenamtlichen Helfern betreut wird.\n\nKennst du schon die Telegram FAQ? Dort findest du Antworten auf die am häufigsten gestellten Fragen.";
"lng_settings_faq_button" = "FAQ öffnen";
"lng_settings_ask_ok" = "Frage stellen";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_logout" = "Abmelden";
"lng_sure_logout" = "Du kannst Telegram von all deinen Geräten gleichzeitig nutzen. Wirklich abmelden?";
@@ -352,9 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Bearbeiten";
"lng_profile_enable_notifications" = "Benachrichtigungen";
"lng_profile_clear_history" = "Chatverlauf löschen";
"lng_profile_delete_conversation" = "Verlauf löschen";
"lng_profile_delete_conversation" = "Chat entfernen";
"lng_profile_clear_and_exit" = "Löschen und verlassen";
"lng_profile_search_messages" = "In diesem Chat suchen";
"lng_profile_block_user" = "Blockieren";
"lng_profile_unblock_user" = "Freigeben";
"lng_profile_block_bot" = "Bot anhalten und blockieren";
"lng_profile_unblock_bot" = "Bot freigeben";
"lng_profile_send_message" = "Nachricht senden";
"lng_profile_share_contact" = "Kontakt teilen";
"lng_profile_invite_to_group" = "In eine Gruppe einladen";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Ich";
"lng_bot_description" = "Was kann dieser Bot?";
"lng_unblock_button" = "Freigeben";
"lng_bot_start" = "Starten";
"lng_bot_choose_group" = "Gruppe auswählen";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
"lng_new_version_text" = "— Direkte Suche in Chats (Chat auswählen und STRG+F drücken)\n— Verlauf in Gruppen löschen (in der Gruppe auf den Gruppennamen tippen)\n— Kontakte, mit denen du nicht chattest, werden nicht mehr in der Übersicht gezeigt";
"lng_new_version_text" = "— Blockiere Nutzer über die Profilseite (im Chat auf den Namen oben tippen)\n— Windows 8, 8.1 und 10: Native Windowsbenachrichtigungen\n— Fehlerbehebung: Eingabemethoden unter Linux (Fcitx und iBus)";
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Intentar ahora";
"lng_status_service_notifications" = "servicio de notificaciones";
"lng_status_support" = "soporte";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "tiene acceso a los mensajes";
"lng_status_bot_not_reads_all" = "no tiene acceso a los mensajes";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notificaciones de escritorio";
"lng_settings_show_name" = "Mostrar el nombre del remitente";
"lng_settings_show_preview" = "Mostrar la vista previa del mensaje";
"lng_settings_use_windows" = "Usar notificaciones de Windows";
"lng_settings_sound_notify" = "Reproducir sonido";
"lng_notification_preview" = "Tienes un nuevo mensaje";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "¿Quieres cerrar esta sesión?";
"lng_settings_reset_button" = "Cerrar";
"lng_settings_reset_done" = "Se cerraron las otras sesiones";
"lng_settings_ask_question" = "Hacer una pregunta";
"lng_settings_ask_sure" = "Por favor, considera que el soporte de Telegram está hecho por voluntarios. Respondemos lo antes posible, pero puede tomar tiempo.\n\nSi quieres, mira las preguntas frecuentes de Telegram: tienen soluciones a problemas y respuestas para la mayoría de las preguntas.";
"lng_settings_faq_button" = "Preguntas frecuentes";
"lng_settings_ask_ok" = "Preguntar";
"lng_settings_faq" = "Preguntas frecuentes";
"lng_settings_logout" = "Cerrar sesión";
"lng_sure_logout" = "¿Quieres cerrar sesión?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "Eliminar chat";
"lng_profile_clear_and_exit" = "Eliminar y salir";
"lng_profile_search_messages" = "Buscar mensajes";
"lng_profile_block_user" = "Bloquear";
"lng_profile_unblock_user" = "Desbloquear";
"lng_profile_block_bot" = "Detener y bloquear el bot";
"lng_profile_unblock_bot" = "Desbloquear el bot";
"lng_profile_send_message" = "Enviar mensaje";
"lng_profile_share_contact" = "Compartir contacto";
"lng_profile_invite_to_group" = "Añadir al grupo";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Tú";
"lng_bot_description" = "¿Qué puede hacer este bot?";
"lng_unblock_button" = "Desbloquear";
"lng_bot_start" = "Iniciar";
"lng_bot_choose_group" = "Elegir grupo";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop fue actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
"lng_new_version_text" = "— Busca mensajes en un chat\n— Borra el historial de mensajes en grupos\n— Los contactos sin mensajes se ocultarán de la lista de chats";
"lng_new_version_text" = "— Bloquea usuarios desde sus perfiles\n— Añadido el soporte para notificaciones Windows toast\n— Arreglados los métodos de entrada en Linux (Fcitx e IBus)";
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Prova ora";
"lng_status_service_notifications" = "notifiche di servizio";
"lng_status_support" = "supporto";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "ha accesso ai messaggi";
"lng_status_bot_not_reads_all" = "non ha accesso ai messaggi";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notifiche desktop";
"lng_settings_show_name" = "Mostra nome del mittente";
"lng_settings_show_preview" = "Mostra anteprima messaggio";
"lng_settings_use_windows" = "Usa le notifiche di Windows";
"lng_settings_sound_notify" = "Riproduci suono";
"lng_notification_preview" = "Hai un nuovo messaggio";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Vuoi terminare questa sessione?";
"lng_settings_reset_button" = "Chiudi";
"lng_settings_reset_done" = "Altre sessioni terminate";
"lng_settings_ask_question" = "Fai una domanda";
"lng_settings_ask_sure" = "Per favore, considera che il supporto su Telegram è offerto da volontari. Proveremo a risponderti il più velocemente possibile, ma potrebbe volerci un po' di tempo.\n\nDai un'occhiata alle FAQ di Telegram: potrai trovare importanti suggerimenti riguardo alcune problematiche e risposte alla maggior parte delle domande.";
"lng_settings_faq_button" = "Vai alle FAQ";
"lng_settings_ask_ok" = "Chiedi";
"lng_settings_faq" = "FAQ di Telegram";
"lng_settings_logout" = "Disconnetti";
"lng_sure_logout" = "Sicuro di volerti disconnettere?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "Elimina chat";
"lng_profile_clear_and_exit" = "Elimina ed esci";
"lng_profile_search_messages" = "Cerca messaggi";
"lng_profile_block_user" = "Blocca utente";
"lng_profile_unblock_user" = "Sblocca utente";
"lng_profile_block_bot" = "Arresta e blocca bot";
"lng_profile_unblock_bot" = "Sblocca bot";
"lng_profile_send_message" = "Invia messaggio";
"lng_profile_share_contact" = "Condividi contatto";
"lng_profile_invite_to_group" = "Aggiungi a un gruppo";
@@ -386,7 +397,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Nuovo gruppo";
"lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi.";
"lng_failed_add_not_mutual" = "Se una persona lascia un gruppo,\nsolo un contatto in comune può reinvitarlo\n(devono avere il tuo numero\ndi telefono, e tu il loro).";
"lng_failed_add_not_mutual" = "Se una persona lascia un gruppo,\nsolo un contatto in comune può reinvitarla\n(lei deve avere il tuo numero\ndi telefono, e tu il suo).";
"lng_sure_delete_contact" = "Sicuro di volere eliminare {contact} dalla tua lista dei contatti?";
"lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata.";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Tu";
"lng_bot_description" = "Cosa può fare questo bot?";
"lng_unblock_button" = "Sblocca";
"lng_bot_start" = "Avvia";
"lng_bot_choose_group" = "Scegli gruppo";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli update è disponibile qui:\n{link}";
"lng_new_version_minor" = "— Bug fix e altri miglioramenti minori";
"lng_new_version_text" = "— Cerca messaggi in una chat\n— Pulisci la cronologia dei messaggi nei gruppi\n— I contatti senza messaggi sono nascosti dalla lista delle chat";
"lng_new_version_text" = "— Blocca gli utenti dalla loro pagina profilo\n— Aggiunto il supporto per le notifiche toast di Windows\n— Risolti i problemi con alcuni metodi di input su Linux (Fcitx and IBus)";
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "다시 시도";
"lng_status_service_notifications" = "서비스 알림";
"lng_status_support" = "지원";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "메시지 접근 권한이 있습니다.";
"lng_status_bot_not_reads_all" = "메시지 접근 권한이 없습니다.";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "데스크탑 알림";
"lng_settings_show_name" = "발신인 표시";
"lng_settings_show_preview" = "메시지 미리보기";
"lng_settings_use_windows" = "윈도우 알림 사용";
"lng_settings_sound_notify" = "소리 재생";
"lng_notification_preview" = "새로운 메시지가 있습니다.";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "해당 세션을 강제 종료 하시겠습니까?";
"lng_settings_reset_button" = "종료";
"lng_settings_reset_done" = "다른 모든 세션이 강제 종료 되었습니다.";
"lng_settings_ask_question" = "질문하기";
"lng_settings_ask_sure" = "텔레그램에 관한 질문은 자원봉사자들이 답변해 드립니다. 신속한 답변을 위해 노력하지만 답변이 다소 늦을 수 있습니다.\n\n일반적인 문제와 해결방법에 대해서는 자주 묻는 질문을 확인해 보세요.";
"lng_settings_faq_button" = "자주 묻는 질문 으로 이동";
"lng_settings_ask_ok" = "질문하기";
"lng_settings_faq" = "텔레그램 자주 묻는 질문";
"lng_settings_logout" = "로그아웃";
"lng_sure_logout" = "로그아웃을 하시겠습니까?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "대화 지우기";
"lng_profile_clear_and_exit" = "삭제 후 종료";
"lng_profile_search_messages" = "메시지 검색";
"lng_profile_block_user" = "차단하기";
"lng_profile_unblock_user" = "차단해제하기";
"lng_profile_block_bot" = "봇 중지 및 차단";
"lng_profile_unblock_bot" = "봇 차단해제";
"lng_profile_send_message" = "메세지 전송";
"lng_profile_share_contact" = "연락처 공유";
"lng_profile_invite_to_group" = "그룹에 추가";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "회원님";
"lng_bot_description" = "봇이 할 수 있는 일은 무엇일까요?";
"lng_unblock_button" = "차단해제";
"lng_bot_start" = "시작";
"lng_bot_choose_group" = "그룹 선택";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
"lng_new_version_text" = "— 대화방내 검색 기능\n— 그룹방 대화내용 삭제\n— 메시지가 없는 대화방은 대화목록에서 숨겨짐";
"lng_new_version_text" = "— 프로필 화면에서 사용자 차단\n— 윈도우 알림 지원\n— 리눅스 입력 방법 수정 (Fcitx and IBus)";
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Probeer nu";
"lng_status_service_notifications" = "servicemeldingen";
"lng_status_support" = "ondersteuning";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "toegang tot berichten";
"lng_status_bot_not_reads_all" = "geen toegang tot berichten";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Desktopmeldingen";
"lng_settings_show_name" = "Afzender weergeven";
"lng_settings_show_preview" = "Voorvertoning weergeven";
"lng_settings_use_windows" = "Windows-berichtgeving gebruiken";
"lng_settings_sound_notify" = "Geluiden afspelen";
"lng_notification_preview" = "Je hebt een nieuw bericht";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Deze sessie beëindigen?";
"lng_settings_reset_button" = "Beëindigen";
"lng_settings_reset_done" = "Alle andere sessies zijn beëindigd";
"lng_settings_ask_question" = "Een vraag stellen";
"lng_settings_ask_sure" = "De ondersteuning voor Telegram wordt gedaan door vrijwilligers. We proberen zo snel mogelijk te reageren maar het kan even duren. \n\nBekijk ook de veelgestelde vragen, deze bevat belangrijke tips en antwoorden op de meest gestelde vragen. ";
"lng_settings_faq_button" = "Veelgestelde vragen";
"lng_settings_ask_ok" = "Vraag";
"lng_settings_faq" = "Veelgestelde vragen";
"lng_settings_logout" = "Uitloggen";
"lng_sure_logout" = "Weet je zeker dat je wilt uitloggen?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "Gesprek verwijderen";
"lng_profile_clear_and_exit" = "Verwijder en verlaat";
"lng_profile_search_messages" = "Zoek berichten";
"lng_profile_block_user" = "Blokkeer gebruiker";
"lng_profile_unblock_user" = "Deblokkeer gebruiker";
"lng_profile_block_bot" = "Stop en blokkeer bot";
"lng_profile_unblock_bot" = "Deblokkeer bot";
"lng_profile_send_message" = "Bericht sturen";
"lng_profile_share_contact" = "Contact delen";
"lng_profile_invite_to_group" = "Groepslid maken";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Jij";
"lng_bot_description" = "Wat kan deze bot? ";
"lng_unblock_button" = "Deblokkeer";
"lng_bot_start" = "Begin";
"lng_bot_choose_group" = "Groep kiezen";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
"lng_new_version_text" = "— Zoek berichten binnen gesprekken\n— Berichtengeschiedenis van groepen wissen\n— Contacten zonder berichten zijn verborgen in de gesprekslijst";
"lng_new_version_text" = "— Blokkeer gebruikers vanaf de profielpagina\n— Ondersteuning voor Windows toast-meldingen\n— Problemen met invoermethodes onder Linux (Fcitx and IBus) opgelost";
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";

View File

@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Tentar agora";
"lng_status_service_notifications" = "notificações de serviço";
"lng_status_support" = "suporte";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "tem acesso as mensagens";
"lng_status_bot_not_reads_all" = "não tem acesso as mensagens";
@@ -185,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notificações na área de trabalho";
"lng_settings_show_name" = "Mostrar nome de quem enviou";
"lng_settings_show_preview" = "Mostrar pré-visualização da mensagem";
"lng_settings_use_windows" = "Usar notificações do Windows";
"lng_settings_sound_notify" = "Tocar som";
"lng_notification_preview" = "Você tem uma nova mensagem";
@@ -323,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Você deseja terminar essa sessão?";
"lng_settings_reset_button" = "Encerrar";
"lng_settings_reset_done" = "Outras sessões encerradas";
"lng_settings_ask_question" = "Fazer uma Pergunta";
"lng_settings_ask_sure" = "Entenda que o suporte do Telegram é feito por voluntários. Tentaremos responder o mais rápido possível, mas poderemos demorar um pouco.\n\nPor favor verifique a página de Perguntas Frequentes do Telegram: há dicas e respostas para a maioria das perguntas.";
"lng_settings_faq_button" = "Perguntas Frequentes";
"lng_settings_ask_ok" = "Perguntar";
"lng_settings_faq" = "Perguntas Frequentes";
"lng_settings_logout" = "Sair";
"lng_sure_logout" = "Tem certeza que deseja sair?";
@@ -355,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_delete_conversation" = "Apagar conversa";
"lng_profile_clear_and_exit" = "Apagar e sair";
"lng_profile_search_messages" = "Buscar mensagens";
"lng_profile_block_user" = "Bloquear usuário";
"lng_profile_unblock_user" = "Desbloquear usuário";
"lng_profile_block_bot" = "Parar e bloquear o bot";
"lng_profile_unblock_bot" = "Desbloquear bot";
"lng_profile_send_message" = "Enviar Mensagem";
"lng_profile_share_contact" = "Compartilhar";
"lng_profile_invite_to_group" = "Adicionar ao Grupo";
@@ -475,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Você";
"lng_bot_description" = "O que esse bot pode fazer?";
"lng_unblock_button" = "Desbloquear";
"lng_bot_start" = "Iniciar";
"lng_bot_choose_group" = "Escolher Grupo";
@@ -629,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
"lng_new_version_minor" = "— Resolução de bugs e outras menores melhorias";
"lng_new_version_text" = "— Buscar mensagens em uma conversa\n— Limpar histórico de mensagens em grupos\n— Contatos sem mensagens estão ocultos da lista de conversas";
"lng_new_version_text" = "— Bloqueie usuários direto da página do perfil\n— Adicionado suporte às notificações de sistema do Windows\n— Consertado métodos de entrada no Linux (Fcitx e IBus)";
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";

View File

@@ -78,12 +78,15 @@ void LocalImageLoaderPrivate::prepareImages() {
type = ToPrepareDocument;
}
}
if (type == ToPrepareDocument) {
mime = mimeTypeForFile(info).name();
}
if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
bool opaque = (mime != stickerMime);
img = App::readImage(file, 0, opaque, &animated);
if (animated) {
type = ToPrepareDocument;
}
}
if (type == ToPrepareDocument) {
mime = mimeTypeForFile(info).name();
}
filename = info.fileName();
filesize = info.size();
@@ -221,7 +224,7 @@ void LocalImageLoaderPrivate::prepareImages() {
}
if (!filesize) filesize = jpeg.size();
photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
thumbId = id;
} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull() && !isSong) {
@@ -254,7 +257,7 @@ void LocalImageLoaderPrivate::prepareImages() {
if (type == ToPrepareDocument) {
document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
} else if (type == ToPrepareAudio) {
audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
}
{

View File

@@ -19,6 +19,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "localstorage.h"
#include "mainwidget.h"
#include "window.h"
#include "lang.h"
namespace {
@@ -540,7 +541,7 @@ namespace {
int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0;
bool _mapChanged = false;
int32 _oldMapVersion = 0;
int32 _oldMapVersion = 0, _oldSettingsVersion = 0;
enum WriteMapWhen {
WriteMapNow,
@@ -737,6 +738,15 @@ namespace {
cSetDesktopNotify(v == 1);
} break;
case dbiWindowsNotifications: {
qint32 v;
stream >> v;
if (!_checkStreamStatus(stream)) return false;
cSetWindowsNotifications(v == 1);
cSetCustomNotifies((App::wnd() ? App::wnd()->psHasNativeNotifications() : true) && !cWindowsNotifications());
} break;
case dbiWorkMode: {
qint32 v;
stream >> v;
@@ -1269,7 +1279,7 @@ namespace {
_writeMap(WriteMapFast);
}
uint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
uint32 size = 13 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
@@ -1285,6 +1295,7 @@ namespace {
data.stream << quint32(dbiSoundNotify) << qint32(cSoundNotify());
data.stream << quint32(dbiDesktopNotify) << qint32(cDesktopNotify());
data.stream << quint32(dbiNotifyView) << qint32(cNotifyView());
data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications());
data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath());
data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath());
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
@@ -1562,6 +1573,9 @@ namespace {
_readMtpData();
LOG(("Map read time: %1").arg(getms() - ms));
if (_oldSettingsVersion < AppVersion) {
Local::writeSettings();
}
return Local::ReadMapDone;
}
@@ -1809,6 +1823,7 @@ namespace Local {
cSetDcOptions(dcOpts);
}
_oldSettingsVersion = settingsData.version;
_settingsSalt = salt;
}
@@ -1951,6 +1966,10 @@ namespace Local {
return _oldMapVersion;
}
int32 oldSettingsVersion() {
return _oldSettingsVersion;
}
void writeDraft(const PeerId &peer, const MessageDraft &draft) {
if (!_working()) return;
@@ -2810,12 +2829,9 @@ namespace Local {
if (App::userFromPeer(user->id) == MTP::authedId()) {
user->input = MTP_inputPeerSelf();
user->inputUser = MTP_inputUserSelf();
} else if (user->contact > 0 || !user->access) {
user->input = MTP_inputPeerContact(MTP_int(App::userFromPeer(user->id)));
user->inputUser = MTP_inputUserContact(MTP_int(App::userFromPeer(user->id)));
} else {
user->input = MTP_inputPeerForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access));
user->inputUser = MTP_inputUserForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access));
user->input = MTP_inputPeerUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
user->inputUser = MTP_inputUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
}
user->photo = photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc);

View File

@@ -100,6 +100,8 @@ namespace Local {
ReadMapState readMap(const QByteArray &pass);
int32 oldMapVersion();
int32 oldSettingsVersion();
struct MessageDraft {
MessageDraft(MsgId replyTo = 0, QString text = QString(), bool previewCancelled = false) : replyTo(replyTo), text(text), previewCancelled(previewCancelled) {
}

View File

@@ -39,6 +39,9 @@ int main(int argc, char *argv[]) {
logsInit();
Local::readSettings();
if (Local::oldSettingsVersion() < AppVersion) {
psNewVersion();
}
if (cFromAutoStart() && !cAutoStart()) {
psAutoStart(false, true);
Local::stop();

View File

@@ -1006,8 +1006,8 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
WebPageData *page = App::webPage(webPageId);
media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill)));
}
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup));
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, MTPnullEntities));
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, MTPnullEntities), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
finishForwarding(hist);
@@ -1734,7 +1734,7 @@ void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia &
QString sendingText, leftText = msg;
HistoryItem *item = 0;
while (textSplit(sendingText, leftText, MaxMessageSize)) {
item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup), unread ? 1 : 2);
item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup, MTPnullEntities), unread ? 1 : 2);
}
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
@@ -3040,8 +3040,7 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe
switch (peer.c_inputNotifyPeer().vpeer.type()) {
case mtpc_inputPeerEmpty: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(0))), settings); break;
case mtpc_inputPeerSelf: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(MTP::authedId()))), settings); break;
case mtpc_inputPeerContact: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerContact().vuser_id)), settings); break;
case mtpc_inputPeerForeign: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerForeign().vuser_id)), settings); break;
case mtpc_inputPeerUser: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerUser().vuser_id)), settings); break;
case mtpc_inputPeerChat: applyNotifySetting(MTP_notifyPeer(MTP_peerChat(peer.c_inputNotifyPeer().vpeer.c_inputPeerChat().vchat_id)), settings); break;
}
break;
@@ -3350,7 +3349,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) {
return;
}
bool out = (d.vflags.v & MTPDmessage_flag_out);
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup));
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities));
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
@@ -3370,7 +3369,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) {
_byPtsUpdates.insert(ptsKey(SkippedUpdates), updates);
return;
}
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup));
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities));
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
@@ -3650,6 +3649,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateUserBlocked: {
const MTPDupdateUserBlocked &d(update.c_updateUserBlocked());
if (UserData *user = App::userLoaded(d.vuser_id.v)) {
user->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
App::markPeerUpdated(user);
}
} break;
case mtpc_updateNewAuthorization: {

View File

@@ -775,18 +775,14 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
_width = _w;
if (_photo->user == WebPageUserId && _msgid) {
if (HistoryItem *item = App::histItemById(_msgid)) {
if (dynamic_cast<HistoryForwarded*>(item)) {
_from = static_cast<HistoryForwarded*>(item)->fromForwarded();
} else {
_from = item->from();
}
if (_msgid && item) {
if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
_from = fwd->fromForwarded();
} else {
_from = App::user(_photo->user);
_from = item->from();
}
} else {
_from = App::user(_photo->user);
_from = _user;
}
updateControls();
_photo->full->load();
@@ -955,10 +951,10 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
}
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
if (HistoryForwarded *fwd = dynamic_cast<HistoryForwarded*>(item)) {
_from = fwd->fromForwarded()->asUser();
if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
_from = fwd->fromForwarded();
} else {
_from = item->from()->asUser();
_from = item->from();
}
_full = 1;
updateControls();
@@ -1850,7 +1846,7 @@ void MediaView::loadBack() {
if (App::main()) App::main()->loadMediaBack(_history->peer, _overview);
} else if (_user && _user->photosCount != 0) {
int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_long(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
}
}

View File

@@ -150,6 +150,13 @@ with open('scheme.tl') as f:
print('Bad param found: "' + param + '" in line: ' + line);
continue;
ptype = pmasktype.group(3);
if (ptype.find('<') >= 0):
templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype);
if (templ):
ptype = templ.group(1) + 'MTP' + templ.group(2).replace('.', '_') + '>';
else:
print('Bad template type: ' + ptype);
continue;
if (not pname in conditions):
conditionsList.append(pname);
conditions[pname] = pmasktype.group(2);

View File

@@ -52,6 +52,7 @@ enum {
};
static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector<MTPKeyboardButtonRow>(0));
static const MTPVector<MTPMessageEntity> MTPnullEntities = MTP_vector<MTPMessageEntity>(0);
#include "mtproto/mtpPublicRSA.h"
#include "mtproto/mtpAuthKey.h"

View File

@@ -366,7 +366,7 @@ static const mtpTypeId mtpLayers[] = {
mtpc_invokeWithLayer17,
mtpc_invokeWithLayer18,
}, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
static const mtpPrime mtpCurrentLayer = 32;
static const mtpPrime mtpCurrentLayer = 34;
template <typename bareT>
class MTPBoxed : public bareT {

View File

@@ -487,33 +487,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputPeerSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputPeerContact:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerContact");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputPeerForeign:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerForeign");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputPeerChat:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -527,6 +500,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_inputPeerUser:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerUser");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputUserEmpty:
to.add("{ inputUserEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
@@ -535,24 +522,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputUserSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputUserContact:
case mtpc_inputUser:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputUserContact");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputUserForeign:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputUserForeign");
to.add("{ inputUser");
to.add("\n").addSpaces(lev);
}
switch (stage) {
@@ -1374,6 +1348,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 8: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 9: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 10: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPDmessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 11: to.add(" entities: "); ++stages.back(); if (flag & MTPDmessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -1662,10 +1637,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" geo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -1740,9 +1713,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
@@ -2221,10 +2194,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_messages_messageEmpty:
to.add("{ messages_messageEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_messages_sentMessage:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -2236,8 +2205,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" entities: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -2336,6 +2306,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputMessagesFilterUrl:
to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_updateNewMessage:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -2847,6 +2821,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 7: to.add(" fwd_from_id: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_fwd_from_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 8: to.add(" fwd_date: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_fwd_date) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 9: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 10: to.add(" entities: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -2870,6 +2845,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 8: to.add(" fwd_from_id: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_fwd_from_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 9: to.add(" fwd_date: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_fwd_date) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 10: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 11: to.add(" entities: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -3513,12 +3489,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -4389,6 +4364,179 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_help_appChangelogEmpty:
to.add("{ help_appChangelogEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_help_appChangelog:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ help_appChangelog");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityUnknown:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityUnknown");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityMention:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityMention");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityHashtag:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityHashtag");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityBotCommand:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityBotCommand");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityUrl:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityUrl");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityEmail:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityEmail");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityBold:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityBold");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityItalic:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityItalic");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityCode:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityCode");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityPre:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityPre");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" language: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityTextUrl:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityTextUrl");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_req_pq:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -5442,6 +5590,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 3: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" random_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 6: to.add(" entities: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -5786,7 +5935,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
@@ -6201,6 +6350,22 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_help_getAppChangelog:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ help_getAppChangelog");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_rpc_result:
if (stage) {
to.add(",\n").addSpaces(lev);

File diff suppressed because it is too large Load Diff

View File

@@ -132,14 +132,10 @@ null#56730bcc = Null;
inputPeerEmpty#7f3b18ea = InputPeer;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerContact#1023dbe8 user_id:int = InputPeer;
inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
inputPeerChat#179be863 chat_id:int = InputPeer;
inputUserEmpty#b98886cf = InputUser;
inputUserSelf#f7c1b13f = InputUser;
inputUserContact#86e94f65 user_id:int = InputUser;
inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
@@ -216,7 +212,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
message#c3060325 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup = Message;
message#f07814c8 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> = Message;
messageService#1d86f70e flags:int id:int from_id:int to_id:Peer date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@@ -237,14 +233,14 @@ messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
dialog#c1dd804a peer:Peer top_message:int read_inbox_max_id:int unread_count:int notify_settings:PeerNotifySettings = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#c3838076 id:long access_hash:long user_id:int date:int geo:GeoPoint sizes:Vector<PhotoSize> = Photo;
photo#cded42fe id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
videoEmpty#c10658a8 id:long = Video;
video#ee9f4a4d id:long access_hash:long user_id:int date:int duration:int size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
video#f72887d3 id:long access_hash:long date:int duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#2049d70c long:double lat:double = GeoPoint;
@@ -307,9 +303,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messageEmpty#3f4e0648 = messages.Message;
messages.sentMessage#4c3d47f3 id:int date:int media:MessageMedia pts:int pts_count:int = messages.SentMessage;
messages.sentMessage#8a99d8e0 id:int date:int media:MessageMedia entities:Vector<MessageEntity> pts:int pts_count:int = messages.SentMessage;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
@@ -325,6 +319,7 @@ inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
@@ -346,8 +341,8 @@ updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Ve
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
updatesTooLong#e317af7e = Updates;
updateShortMessage#ed5c2127 flags:# id:int user_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int = Updates;
updateShortChatMessage#52238b3c flags:# id:int from_id:int chat_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int = Updates;
updateShortMessage#3f32d858 flags:# id:int user_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int entities:flags.7?Vector<MessageEntity> = Updates;
updateShortChatMessage#f9409b3d flags:# id:int from_id:int chat_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int entities:flags.7?Vector<MessageEntity> = Updates;
updateShort#78d4dec1 update:Update date:int = Updates;
updatesCombined#725b04c3 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq_start:int seq:int = Updates;
updates#74ae4240 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq:int = Updates;
@@ -454,7 +449,7 @@ inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
audioEmpty#586988d8 id:long = Audio;
audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio;
audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio;
documentEmpty#36f8c871 id:long = Document;
document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
@@ -607,6 +602,25 @@ replyKeyboardHide#a03e5b85 flags:# = ReplyMarkup;
replyKeyboardForceReply#f4108aa0 flags:# = ReplyMarkup;
replyKeyboardMarkup#3502758c flags:# rows:Vector<KeyboardButtonRow> = ReplyMarkup;
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
inputUser#d8292816 user_id:int access_hash:long = InputUser;
help.appChangelogEmpty#af7e0394 = help.AppChangelog;
help.appChangelog#4668e6bd text:string = help.AppChangelog;
messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
messageEntityMention#fa04579d offset:int length:int = MessageEntity;
messageEntityHashtag#6f635b0d offset:int length:int = MessageEntity;
messageEntityBotCommand#6cef8ac7 offset:int length:int = MessageEntity;
messageEntityUrl#6ed02538 offset:int length:int = MessageEntity;
messageEntityEmail#64e475c2 offset:int length:int = MessageEntity;
messageEntityBold#bd610bc9 offset:int length:int = MessageEntity;
messageEntityItalic#826f8b60 offset:int length:int = MessageEntity;
messageEntityCode#28a20571 offset:int length:int = MessageEntity;
messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity;
messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -658,7 +672,7 @@ messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHis
messages.deleteMessages#a5f18925 id:Vector<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
messages.sendMessage#fc55e6b5 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup = messages.SentMessage;
messages.sendMessage#df12390 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = messages.SentMessage;
messages.sendMedia#c8f16791 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates;
messages.forwardMessages#55e1728d peer:InputPeer id:Vector<int> random_id:Vector<long> = Updates;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
@@ -685,7 +699,7 @@ help.getAppUpdate#c812ac7e device_model:string system_version:string app_version
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getInviteText#a4a95186 lang_code:string = help.InviteText;
photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos;
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates;
messages.sendBroadcast#bf73f4da contacts:Vector<InputUser> random_id:Vector<long> message:string media:InputMedia = Updates;
@@ -770,3 +784,5 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet
messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
messages.startBot#1b3e0ffc bot:InputUser chat_id:int random_id:long start_param:string = Updates;
help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog;

View File

@@ -56,11 +56,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
// settings
_enableNotifications(this, lang(lng_profile_enable_notifications)),
// actions
_searchInPeer(this, lang(lng_profile_search_messages)),
_clearHistory(this, lang(lng_profile_clear_history)),
_deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)),
// shared media
_allMediaTypes(false),
_mediaShowAll(this, lang(lng_profile_show_all_types)),
@@ -69,6 +64,14 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_mediaDocuments(this, QString()),
_mediaAudios(this, QString()),
// actions
_searchInPeer(this, lang(lng_profile_search_messages)),
_clearHistory(this, lang(lng_profile_clear_history)),
_deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)),
_wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown),
_blockRequest(0),
_blockUser(this, lang((_peerUser && _peerUser->botInfo) ? lng_profile_block_bot : lng_profile_block_user), st::btnRedLink),
// participants
_pHeight(st::profileListPhotoSize + st::profileListPadding.height() * 2),
_kickWidth(st::linkFont->m.width(lang(lng_profile_kick))),
@@ -80,12 +83,15 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
if (_peerUser) {
if (_peerUser->blocked == UserIsBlocked) {
_blockUser.setText(lang(_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user));
}
_phoneText = App::formatPhone(_peerUser->phone);
PhotoData *userPhoto = (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) ? App::photo(_peerUser->photoId) : 0;
if (userPhoto && userPhoto->date) {
_photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer));
}
if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date)) {
if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date) || (_peerUser->blocked == UserBlockUnknown)) {
App::api()->requestFullPeer(_peer);
}
} else {
@@ -153,11 +159,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
// settings
connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications()));
// actions
connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
// shared media
connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll()));
connect(&_mediaPhotos, SIGNAL(clicked()), this, SLOT(onMediaPhotos()));
@@ -170,6 +171,12 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_mediaLinks[OverviewAudios] = &_mediaAudios;
App::main()->preloadOverviews(_peer);
// actions
connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser()));
App::contextItem(0);
resizeEvent(0);
@@ -281,6 +288,28 @@ void ProfileInner::onDeleteConversationSure() {
}
}
void ProfileInner::onBlockUser() {
if (!_peerUser || _blockRequest) return;
if (_peerUser->blocked == UserIsBlocked) {
_blockRequest = MTP::send(MTPcontacts_Unblock(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, false), rpcFail(&ProfileInner::blockFail));
} else {
_blockRequest = MTP::send(MTPcontacts_Block(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, true), rpcFail(&ProfileInner::blockFail));
}
}
void ProfileInner::blockDone(bool blocked, const MTPBool &result) {
_blockRequest = 0;
if (!_peerUser) return;
_peerUser->blocked = blocked ? UserIsBlocked : UserIsNotBlocked;
emit App::main()->peerUpdated(_peerUser);
}
bool ProfileInner::blockFail(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
//_blockRequest = 0;
return false;
}
void ProfileInner::onAddParticipant() {
App::wnd()->showLayer(new ContactsBox(_peerChat));
}
@@ -410,6 +439,10 @@ void ProfileInner::peerUpdated(PeerData *data) {
if (_peerUser) {
_phoneText = App::formatPhone(_peerUser->phone);
if (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) photo = App::photo(_peerUser->photoId);
if (_wasBlocked != _peerUser->blocked) {
_wasBlocked = _peerUser->blocked;
_blockUser.setText(lang((_peerUser->blocked == UserIsBlocked) ? (_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_peerUser->botInfo ? lng_profile_block_bot : lng_profile_block_user)));
}
} else {
if (_peerChat->photoId && _peerChat->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChat->photoId);
}
@@ -595,14 +628,6 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
top += _enableNotifications.height();
// actions
p.setFont(st::profileHeaderFont->f);
p.setPen(st::profileHeaderColor->p);
p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
top += st::profileHeaderSkip;
top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
// shared media
p.setFont(st::profileHeaderFont->f);
p.setPen(st::profileHeaderColor->p);
@@ -644,6 +669,15 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
top += _mediaLinks[OverviewPhotos]->height();
}
// actions
p.setFont(st::profileHeaderFont->f);
p.setPen(st::profileHeaderColor->p);
p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
top += st::profileHeaderSkip;
top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
if (_peerUser && App::userFromPeer(_peerUser->id) != MTP::authedId()) top += st::setSectionSkip + _blockUser.height();
// participants
if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
QString sectionHeader = lang(_participants.isEmpty() ? lng_profile_loading : lng_profile_participants_section);
@@ -741,7 +775,7 @@ void ProfileInner::updateSelected() {
update(QRect(_left, _aboutTop, _width, _aboutHeight));
}
int32 partfrom = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
int32 partfrom = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
int32 newSelected = (lp.x() >= _left - st::profileListPadding.width() && lp.x() < _left + _width + st::profileListPadding.width() && lp.y() >= partfrom) ? (lp.y() - partfrom) / _pHeight : -1;
UserData *newKickOver = 0;
@@ -889,12 +923,6 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
top += st::profileHeaderSkip;
_enableNotifications.move(_left, top); top += _enableNotifications.height();
// actions
top += st::profileHeaderSkip;
_searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip;
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
_deleteConversation.move(_left, top); top += _deleteConversation.height();
// shared media
top += st::profileHeaderSkip;
@@ -914,6 +942,16 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
}
top += _mediaLinks[OverviewPhotos]->height();
// actions
top += st::profileHeaderSkip;
_searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip;
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
_deleteConversation.move(_left, top); top += _deleteConversation.height();
if (_peerUser && App::userFromPeer(_peerUser->id) != MTP::authedId()) {
top += st::setSectionSkip;
_blockUser.move(_left, top); top += _blockUser.height();
}
// participants
if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
top += st::profileHeaderSkip;
@@ -1047,7 +1085,7 @@ void ProfileInner::showAll() {
_addParticipant.hide();
}
}
_enableNotifications.show();
_blockUser.hide();
} else {
_uploadPhoto.hide();
_cancelPhoto.hide();
@@ -1066,9 +1104,14 @@ void ProfileInner::showAll() {
_shareContact.show();
_inviteToGroup.hide();
}
_enableNotifications.show();
_clearHistory.show();
if (App::userFromPeer(_peerUser->id) != MTP::authedId()) {
_blockUser.show();
} else {
_blockUser.hide();
}
}
_enableNotifications.show();
updateNotifySettings();
// shared media
@@ -1111,15 +1154,13 @@ void ProfileInner::showAll() {
reorderParticipants();
int32 h;
if (_peerUser) {
h = _mediaShowAll.y() + _mediaShowAll.height() + st::profileHeaderSkip;
if (_mediaShowAll.isHidden()) {
for (int i = 0; i < OverviewCount; ++i) {
if (i == OverviewAudioDocuments) continue;
if (!_mediaLinks[i]->isHidden()) h += _mediaLinks[i]->height() + st::setLittleSkip;
}
if (App::userFromPeer(_peerUser->id) == MTP::authedId()) {
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
} else {
h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip;
}
} else {
h = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
if (!_participants.isEmpty()) {
h += st::profileHeaderSkip + _participants.size() * _pHeight;
} else if (_peerChat->count > 0) {

View File

@@ -75,6 +75,7 @@ public slots:
void onClearHistorySure();
void onDeleteConversation();
void onDeleteConversationSure();
void onBlockUser();
void onAddParticipant();
void onUpdatePhoto();
@@ -146,15 +147,18 @@ private:
// settings
FlatCheckbox _enableNotifications;
// actions
LinkButton _searchInPeer, _clearHistory, _deleteConversation;
// shared media
bool _allMediaTypes;
LinkButton _mediaShowAll, _mediaPhotos, _mediaVideos, _mediaDocuments, _mediaAudios;
LinkButton *_mediaLinks[OverviewCount];
QString overviewLinkText(int32 type, int32 count);
// actions
LinkButton _searchInPeer, _clearHistory, _deleteConversation;
UserBlockedStatus _wasBlocked;
mtpRequestId _blockRequest;
LinkButton _blockUser;
// participants
int32 _pHeight;
int32 _kickWidth, _selectedRow, _lastPreload;
@@ -176,6 +180,9 @@ private:
QString _onlineText;
ContextMenu *_menu;
void blockDone(bool blocked, const MTPBool &result);
bool blockFail(const RPCError &error);
};
class ProfileWidget : public QWidget, public RPCSender, public Animated {

View File

@@ -1249,6 +1249,10 @@ void psRegisterCustomScheme() {
}
}
void psNewVersion() {
psRegisterCustomScheme();
}
bool _execUpdater(bool update = true) {
static const int MaxLen = 65536, MaxArgsCount = 128;

View File

@@ -68,6 +68,10 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications() {
return false;
}
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -159,7 +163,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(QWidget *widget);
inline QString psConvertFileUrl(const QString &url) {

View File

@@ -564,7 +564,9 @@ void psClearInitLogs() {
}
void psActivateProcess(uint64 pid) {
objc_activateProgram();
if (!pid) {
objc_activateProgram(App::wnd() ? App::wnd()->winId() : 0);
}
}
QString psCurrentCountry() {
@@ -651,7 +653,7 @@ void psFinish() {
objc_finish();
}
void psRegisterCustomScheme() {
void psNewVersion() {
objc_registerCustomScheme();
}

View File

@@ -83,6 +83,10 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications() {
return !(QSysInfo::macVersion() < QSysInfo::MV_10_8);
}
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -189,7 +193,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(QWidget *widget);
QString psConvertFileUrl(const QString &url);

View File

@@ -73,7 +73,7 @@ void objc_execTelegram();
void objc_registerCustomScheme();
void objc_activateProgram();
void objc_activateProgram(WId winId);
bool objc_moveFile(const QString &from, const QString &to);
void objc_deleteDir(const QString &dir);

View File

@@ -982,8 +982,12 @@ void objc_execTelegram() {
_execUpdater(NO);
}
void objc_activateProgram() {
void objc_activateProgram(WId winId) {
[NSApp activateIgnoringOtherApps:YES];
if (winId) {
NSWindow *w = [reinterpret_cast<NSView*>(winId) window];
[w makeKeyAndOrderFront:NSApp];
}
}
bool objc_moveFile(const QString &from, const QString &to) {

File diff suppressed because it is too large Load Diff

View File

@@ -67,6 +67,9 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications();
void psCleanNotifyPhotosIn(int32 dt);
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -77,6 +80,8 @@ public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu();
void psCleanNotifyPhotos();
protected:
bool psHasTrayIcon() const {
@@ -100,6 +105,8 @@ private:
HMENU ps_menu;
HICON ps_iconBig, ps_iconSmall, ps_iconOverlay;
SingleTimer ps_cleanNotifyPhotosTimer;
void psDestroyIcons();
};
@@ -161,7 +168,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(TWidget *widget);
inline QString psConvertFileUrl(const QString &url) {

View File

@@ -42,6 +42,7 @@ QString gDialogLastPath, gDialogHelperPath; // optimize QFileDialog
bool gSoundNotify = true;
bool gDesktopNotify = true;
DBINotifyView gNotifyView = dbinvShowPreview;
bool gWindowsNotifications = true;
bool gStartMinimized = false;
bool gStartInTray = false;
bool gAutoStart = false;
@@ -119,11 +120,7 @@ QString gLangFile;
bool gRetina = false;
float64 gRetinaFactor = 1.;
int32 gIntRetinaFactor = 1;
#ifdef Q_OS_MAC
bool gCustomNotifies = false;
#else
bool gCustomNotifies = true;
#endif
uint64 gInstance = 0.;
#ifdef Q_OS_WIN
@@ -163,7 +160,6 @@ SavedPeers gSavedPeers;
SavedPeersByTime gSavedPeersByTime;
void settingsParseArgs(int argc, char *argv[]) {
gCustomNotifies = true;
#ifdef Q_OS_MAC
if (QSysInfo::macVersion() < QSysInfo::MV_10_8) {
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));

View File

@@ -101,6 +101,8 @@ DeclareSetting(bool, DesktopNotify);
DeclareSetting(DBINotifyView, NotifyView);
DeclareSetting(bool, AutoUpdate);
DeclareSetting(bool, WindowsNotifications);
struct TWindowPos {
TWindowPos() : moncrc(0), maximized(0), x(0), y(0), w(0), h(0) {
}

View File

@@ -122,6 +122,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
_desktopNotify(this, lang(lng_settings_desktop_notify), cDesktopNotify()),
_senderName(this, lang(lng_settings_show_name), cNotifyView() <= dbinvShowName),
_messagePreview(this, lang(lng_settings_show_preview), cNotifyView() <= dbinvShowPreview),
_windowsNotifications(this, lang(lng_settings_use_windows), cWindowsNotifications()),
_soundNotify(this, lang(lng_settings_sound_notify), cSoundNotify()),
// general
@@ -186,7 +187,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
_connectionTypeText(lang(lng_connection_type) + ' '),
_connectionTypeWidth(st::linkFont->m.width(_connectionTypeText)),
_showSessions(this, lang(lng_settings_show_sessions)),
_logOut(this, lang(lng_settings_logout), st::btnLogout)
_askQuestion(this, lang(lng_settings_ask_question)),
_telegramFAQ(this, lang(lng_settings_faq)),
_logOut(this, lang(lng_settings_logout), st::btnLogout),
_supportGetRequest(0)
{
if (self()) {
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
@@ -217,6 +221,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
connect(&_desktopNotify, SIGNAL(changed()), this, SLOT(onDesktopNotify()));
connect(&_senderName, SIGNAL(changed()), this, SLOT(onSenderName()));
connect(&_messagePreview, SIGNAL(changed()), this, SLOT(onMessagePreview()));
connect(&_windowsNotifications, SIGNAL(changed()), this, SLOT(onWindowsNotifications()));
connect(&_soundNotify, SIGNAL(changed()), this, SLOT(onSoundNotify()));
// general
@@ -288,6 +293,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
connect(&_passwordTurnOff, SIGNAL(clicked()), this, SLOT(onPasswordOff()));
connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType()));
connect(&_showSessions, SIGNAL(clicked()), this, SLOT(onShowSessions()));
connect(&_askQuestion, SIGNAL(clicked()), this, SLOT(onAskQuestion()));
connect(&_telegramFAQ, SIGNAL(clicked()), this, SLOT(onTelegramFAQ()));
connect(&_logOut, SIGNAL(clicked()), App::wnd(), SLOT(onLogout()));
if (App::main()) {
@@ -411,6 +418,9 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
top += _desktopNotify.height() + st::setLittleSkip;
top += _senderName.height() + st::setLittleSkip;
top += _messagePreview.height() + st::setSectionSkip;
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
top += _windowsNotifications.height() + st::setSectionSkip;
}
top += _soundNotify.height();
}
@@ -637,6 +647,9 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
_desktopNotify.move(_left, top); top += _desktopNotify.height() + st::setLittleSkip;
_senderName.move(_left, top); top += _senderName.height() + st::setLittleSkip;
_messagePreview.move(_left, top); top += _messagePreview.height() + st::setSectionSkip;
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
_windowsNotifications.move(_left, top); top += _windowsNotifications.height() + st::setSectionSkip;
}
_soundNotify.move(_left, top); top += _soundNotify.height();
}
@@ -719,7 +732,12 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
_connectionType.move(_left + _connectionTypeWidth, top); top += _connectionType.height() + st::setLittleSkip;
if (self()) {
_showSessions.move(_left, top); top += _showSessions.height() + st::setSectionSkip;
_askQuestion.move(_left, top); top += _askQuestion.height() + st::setLittleSkip;
_telegramFAQ.move(_left, top); top += _telegramFAQ.height() + st::setSectionSkip;
_logOut.move(_left, top);
} else {
top += st::setSectionSkip - st::setLittleSkip;
_telegramFAQ.move(_left, top);
}
}
@@ -745,7 +763,9 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
App::wnd()->showLayer(box);
from = size;
break;
} else if (qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str)) {
} else if (str == qstr("loadlang")) {
chooseCustomLang();
} else if (qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str) || qsl("loadlang").startsWith(str)) {
break;
}
++from;
@@ -810,7 +830,7 @@ bool SettingsInner::animStep(float64 ms) {
void SettingsInner::updateSize(int32 newWidth) {
if (_logOut.isHidden()) {
resize(newWidth, _connectionType.geometry().bottom() + st::setBottom);
resize(newWidth, _telegramFAQ.geometry().bottom() + st::setBottom);
} else {
resize(newWidth, _logOut.geometry().bottom() + st::setBottom);
}
@@ -936,11 +956,17 @@ void SettingsInner::showAll() {
_desktopNotify.show();
_senderName.show();
_messagePreview.show();
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
_windowsNotifications.show();
} else {
_windowsNotifications.hide();
}
_soundNotify.show();
} else {
_desktopNotify.hide();
_senderName.hide();
_messagePreview.hide();
_windowsNotifications.hide();
_soundNotify.hide();
}
@@ -1049,6 +1075,7 @@ void SettingsInner::showAll() {
_passwordTurnOff.show();
}
_showSessions.show();
_askQuestion.show();
_logOut.show();
} else {
_passcodeEdit.hide();
@@ -1057,8 +1084,10 @@ void SettingsInner::showAll() {
_passwordEdit.hide();
_passwordTurnOff.hide();
_showSessions.hide();
_askQuestion.hide();
_logOut.hide();
}
_telegramFAQ.show();
}
void SettingsInner::saveError(const QString &str) {
@@ -1067,6 +1096,17 @@ void SettingsInner::saveError(const QString &str) {
update();
}
void SettingsInner::supportGot(const MTPhelp_Support &support) {
if (!App::main()) return;
if (support.type() == mtpc_help_support) {
const MTPDhelp_support &d(support.c_help_support());
UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, d.vuser));
App::main()->showPeerHistory(u->id, ShowAtUnreadMsgId);
App::wnd()->hideSettings();
}
}
void SettingsInner::onUpdatePhotoCancel() {
if (self()) {
App::app()->cancelPhotoUpdate(self()->id);
@@ -1110,25 +1150,56 @@ void SettingsInner::onShowSessions() {
App::wnd()->showLayer(box);
}
void SettingsInner::onAskQuestion() {
if (!App::self()) return;
ConfirmBox *box = new ConfirmBox(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button));
connect(box, SIGNAL(confirmed()), this, SLOT(onAskQuestionSure()));
connect(box, SIGNAL(cancelPressed()), this, SLOT(onTelegramFAQ()));
App::wnd()->showLayer(box);
}
void SettingsInner::onAskQuestionSure() {
if (_supportGetRequest) return;
_supportGetRequest = MTP::send(MTPhelp_GetSupport(), rpcDone(&SettingsInner::supportGot));
}
void SettingsInner::onTelegramFAQ() {
QString url = qsl("https://telegram.org/faq");
if (cLang() > languageDefault && cLang() < languageCount) {
const char *code = LanguageCodes[cLang()];
if (qstr("de") == code || qstr("es") == code || qstr("it") == code || qstr("ko") == code) {
url += qsl("/") + code;
} else if (qstr("pt_BR") == code) {
url += qsl("/br");
}
}
QDesktopServices::openUrl(url);
}
void SettingsInner::chooseCustomLang() {
QString file;
QByteArray arr;
if (filedialogGetOpenFile(file, arr, qsl("Choose language .strings file"), qsl("Language files (*.strings)"))) {
_testlang = QFileInfo(file).absoluteFilePath();
LangLoaderPlain loader(_testlang, LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_continue));
if (loader.errors().isEmpty()) {
LangLoaderResult result = loader.found();
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_continue, langOriginal(lng_continue)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, cancel);
connect(box, SIGNAL(confirmed()), this, SLOT(onSaveTestLang()));
App::wnd()->showLayer(box);
} else {
App::wnd()->showLayer(new ConfirmBox("Custom lang failed :(\n\nError: " + loader.errors(), true, lang(lng_close)));
}
}
}
void SettingsInner::onChangeLanguage() {
if ((_changeLanguage.clickModifiers() & Qt::ShiftModifier) && (_changeLanguage.clickModifiers() & Qt::AltModifier)) {
QString file;
QByteArray arr;
if (filedialogGetOpenFile(file, arr, qsl("Choose language .strings file"), qsl("Language files (*.strings)"))) {
_testlang = QFileInfo(file).absoluteFilePath();
LangLoaderPlain loader(_testlang, LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_continue));
if (loader.errors().isEmpty()) {
LangLoaderResult result = loader.found();
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_continue, langOriginal(lng_continue)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, cancel);
connect(box, SIGNAL(confirmed()), this, SLOT(onSaveTestLang()));
App::wnd()->showLayer(box);
} else {
App::wnd()->showLayer(new ConfirmBox("Custom lang failed :(\n\nError: " + loader.errors(), true, lang(lng_close)));
}
}
chooseCustomLang();
} else {
App::wnd()->showLayer(new LanguageBox());
}
@@ -1349,6 +1420,13 @@ void SettingsInner::onSoundNotify() {
Local::writeUserSettings();
}
void SettingsInner::onWindowsNotifications() {
cSetWindowsNotifications(!cWindowsNotifications());
App::wnd()->notifyClearFast();
cSetCustomNotifies(!cWindowsNotifications());
Local::writeUserSettings();
}
void SettingsInner::onDesktopNotify() {
cSetDesktopNotify(_desktopNotify.checked());
if (!_desktopNotify.checked()) {

View File

@@ -78,6 +78,8 @@ public:
void showAll();
void chooseCustomLang();
void updateChatBackground();
void needBackgroundUpdate(bool tile);
@@ -125,6 +127,8 @@ public slots:
void onSenderName();
void onMessagePreview();
void onWindowsNotifications();
void onReplaceEmojis();
void onViewEmojis();
@@ -162,10 +166,16 @@ public slots:
void onUpdateLocalStorage();
void onAskQuestion();
void onAskQuestionSure();
void onTelegramFAQ();
private:
void saveError(const QString &str = QString());
void supportGot(const MTPhelp_Support &support);
void setScale(DBIScale newScale);
QString _testlang, _secretText;
@@ -192,7 +202,7 @@ private:
LinkButton _chooseUsername;
// notifications
FlatCheckbox _desktopNotify, _senderName, _messagePreview, _soundNotify;
FlatCheckbox _desktopNotify, _senderName, _messagePreview, _windowsNotifications, _soundNotify;
// general
LinkButton _changeLanguage;
@@ -261,9 +271,11 @@ private:
LinkButton _connectionType;
QString _connectionTypeText;
int32 _connectionTypeWidth;
LinkButton _showSessions;
LinkButton _showSessions, _askQuestion, _telegramFAQ;
FlatButton _logOut;
mtpRequestId _supportGetRequest;
void gotPassword(const MTPaccount_Password &result);
void offPasswordDone(const MTPBool &result);
bool offPasswordFail(const RPCError &error);

View File

@@ -35,5 +35,7 @@ Q_IMPORT_PLUGIN(QWbmpPlugin)
Q_IMPORT_PLUGIN(QWebpPlugin)
#elif defined Q_OS_LINUX
Q_IMPORT_PLUGIN(QComposePlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QIbusPlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QFcitxPlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QWebpPlugin)
#endif

View File

@@ -16,7 +16,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#define __HUGE
#define PSAPI_VERSION 1 // fix WinXP
//#define Q_NO_TEMPLATE_FRIENDS // fix some compiler difference issues
#include <openssl/bn.h>

View File

@@ -404,7 +404,7 @@ QString saveFileName(const QString &title, const QString &filter, const QString
void VideoOpenLink::onClick(Qt::MouseButton button) const {
VideoData *data = video();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
QString already = data->already(true);
if (!already.isEmpty()) {
@@ -424,7 +424,7 @@ void VideoOpenLink::onClick(Qt::MouseButton button) const {
}
void VideoSaveLink::doSave(VideoData *data, bool forceSavingAs) {
if (!data->user && !data->date) return;
if (!data->date) return;
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
@@ -456,13 +456,13 @@ void VideoSaveLink::onClick(Qt::MouseButton button) const {
void VideoCancelLink::onClick(Qt::MouseButton button) const {
VideoData *data = video();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
data->cancel();
}
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
}
@@ -482,7 +482,7 @@ QString VideoData::already(bool check) {
void AudioOpenLink::onClick(Qt::MouseButton button) const {
AudioData *data = audio();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
QString already = data->already(true);
bool play = App::hoveredLinkItem() && audioPlayer();
@@ -516,7 +516,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
}
void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) {
if (!data->user && !data->date) return;
if (!data->date) return;
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
@@ -549,7 +549,7 @@ void AudioSaveLink::onClick(Qt::MouseButton button) const {
void AudioCancelLink::onClick(Qt::MouseButton button) const {
AudioData *data = audio();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
data->cancel();
}
@@ -569,8 +569,8 @@ bool StickerData::setInstalled() const {
return false;
}
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
}

View File

@@ -167,9 +167,15 @@ struct BotInfo {
QString startToken, startGroupToken;
};
enum UserBlockedStatus {
UserBlockUnknown = 0,
UserIsBlocked,
UserIsNotBlocked,
};
struct PhotoData;
struct UserData : public PeerData {
UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1), botInfo(0) {
UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), blocked(UserBlockUnknown), photosCount(-1), botInfo(0) {
}
void setPhoto(const MTPUserProfilePhoto &photo);
void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username);
@@ -192,6 +198,7 @@ struct UserData : public PeerData {
TextLinkPtr lnk;
int32 onlineTill;
int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
UserBlockedStatus blocked;
typedef QList<PhotoData*> Photos;
Photos photos;
@@ -230,8 +237,8 @@ inline int32 newMessageFlags(PeerData *p) {
typedef QMap<char, QPixmap> PreparedPhotoThumbs;
struct PhotoData {
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
id(id), access(access), user(user), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
}
void forget() {
thumb->forget();
@@ -254,7 +261,6 @@ struct PhotoData {
}
PhotoId id;
uint64 access;
int32 user;
int32 date;
ImagePtr thumb, replyPreview;
ImagePtr medium;
@@ -294,7 +300,7 @@ enum FileStatus {
};
struct VideoData {
VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
void forget() {
thumb->forget();
@@ -330,7 +336,6 @@ struct VideoData {
VideoId id;
uint64 access;
int32 user;
int32 date;
int32 duration;
int32 w, h;
@@ -390,7 +395,7 @@ public:
};
struct AudioData {
AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
void forget() {
}
@@ -425,7 +430,6 @@ struct AudioData {
AudioId id;
uint64 access;
int32 user;
int32 date;
QString mime;
int32 duration;

View File

@@ -232,55 +232,56 @@ QString translitRusEng(const QString &rus);
QString rusKeyboardLayoutSwitch(const QString &from);
enum DataBlockId {
dbiKey = 0x00,
dbiUser = 0x01,
dbiDcOptionOld = 0x02,
dbiMaxGroupCount = 0x03,
dbiMutePeer = 0x04,
dbiSendKey = 0x05,
dbiAutoStart = 0x06,
dbiStartMinimized = 0x07,
dbiSoundNotify = 0x08,
dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 0x0e,
dbiConnectionType = 0x0f,
dbiKey = 0x00,
dbiUser = 0x01,
dbiDcOptionOld = 0x02,
dbiMaxGroupCount = 0x03,
dbiMutePeer = 0x04,
dbiSendKey = 0x05,
dbiAutoStart = 0x06,
dbiStartMinimized = 0x07,
dbiSoundNotify = 0x08,
dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 0x0e,
dbiConnectionType = 0x0f,
// 0x10 reserved
dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 0x14,
dbiDownloadPath = 0x15,
dbiScale = 0x16,
dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 0x18,
dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 0x1a,
dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 0x14,
dbiDownloadPath = 0x15,
dbiScale = 0x16,
dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 0x18,
dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 0x1a,
// 0x1b reserved
dbiNotifyView = 0x1c,
dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 0x1e,
dbiLang = 0x1f,
dbiLangFile = 0x20,
dbiTileBackground = 0x21,
dbiAutoLock = 0x22,
dbiDialogLastPath = 0x23,
dbiRecentEmojis = 0x24,
dbiEmojiVariants = 0x25,
dbiRecentStickers = 0x26,
dbiDcOption = 0x27,
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiNotifyView = 0x1c,
dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 0x1e,
dbiLang = 0x1f,
dbiLangFile = 0x20,
dbiTileBackground = 0x21,
dbiAutoLock = 0x22,
dbiDialogLastPath = 0x23,
dbiRecentEmojis = 0x24,
dbiEmojiVariants = 0x25,
dbiRecentStickers = 0x26,
dbiDcOption = 0x27,
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiWindowsNotifications = 0x30,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
// 500-600 reserved
dbiVersion = 666,
dbiVersion = 666,
};
enum DBISendKey {

View File

@@ -1467,8 +1467,8 @@ void Window::notifyShowNext(NotifyWindow *remove) {
uint64 ms = getms(true);
History *history = notifyItem->history();
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
if (j == notifyWhenMaps.end()) {
bool notifyWhenFound = (j != notifyWhenMaps.cend());
if (!notifyWhenFound) {
history->clearNotifications();
} else {
HistoryItem *nextNotify = 0;
@@ -1516,7 +1516,7 @@ void Window::notifyShowNext(NotifyWindow *remove) {
if (!history->hasNotification()) {
if (notifyWaiter != notifyWaiters.cend()) notifyWaiters.erase(notifyWaiter);
if (j != notifyWhenMaps.cend()) notifyWhenMaps.erase(j);
if (notifyWhenFound) notifyWhenMaps.erase(j);
continue;
}
}

View File

@@ -11,7 +11,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.48</string>
<string>0.8.51</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleSignature</key>

View File

@@ -312,7 +312,10 @@ INCLUDEPATH += "/usr/include/dee-1.0"
INCLUDEPATH += "/usr/include/libdbusmenu-glib-0.4"
LIBS += -lcrypto -lssl -lz -ldl -llzma -lexif -lopenal -lavformat -lavcodec -lswresample -lavutil -lopus
LIBS += ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.a
LIBS += ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.a \
./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libibusplatforminputcontextplugin.a \
./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.a
LIBS += /usr/local/lib/libxkbcommon.a
RESOURCES += \
./SourceFiles/telegram.qrc \

Binary file not shown.

View File

@@ -54,14 +54,17 @@
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<CustomBuildBeforeTargets>
</CustomBuildBeforeTargets>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -80,7 +83,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Debug;.\..\..\Libraries\libexif-0.6.20\win32\Debug;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Debug;.\..\..\Libraries\openal-soft\build\Debug;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatDebug;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers />
<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
@@ -108,7 +111,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers />
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
<ProfileGuidedDatabase>$(IntDir)$(TargetName).pgd</ProfileGuidedDatabase>
@@ -136,7 +139,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>
</ImageHasSafeExceptionHandlers>
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>

View File

@@ -1707,7 +1707,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.48;
CURRENT_PROJECT_VERSION = 0.8.51;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -1725,7 +1725,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 0.8.48;
CURRENT_PROJECT_VERSION = 0.8.51;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1751,10 +1751,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.48;
CURRENT_PROJECT_VERSION = 0.8.51;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.48;
DYLIB_CURRENT_VERSION = 0.8.51;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1885,10 +1885,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.48;
CURRENT_PROJECT_VERSION = 0.8.51;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.48;
DYLIB_CURRENT_VERSION = 0.8.51;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;

View File

@@ -1,2 +1,2 @@
echo 0.8 8048 0.8.48 0
echo 0.8 8051 0.8.51 0
# AppVersionStrMajor AppVersion AppVersionStr DevChannel

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
TARGET = composeplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QComposePlatformInputContextPlugin
load(qt_plugin)
QT += gui-private
DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
SOURCES += $$PWD/qcomposeplatforminputcontextmain.cpp \
$$PWD/qcomposeplatforminputcontext.cpp \
$$PWD/generator/qtablegenerator.cpp \
HEADERS += $$PWD/qcomposeplatforminputcontext.h \
$$PWD/generator/qtablegenerator.h \
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
# dont't need x11 dependency for compose key plugin
QT_CONFIG -= use-xkbcommon-x11support
# include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
}
OTHER_FILES += $$PWD/compose.json

View File

@@ -0,0 +1,3 @@
{
"Keys": [ "fcitx" ]
}

View File

@@ -0,0 +1,38 @@
TARGET = fcitxplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QFcitxPlatformInputContextPlugin
load(qt_plugin)
QT += dbus gui-private
SOURCES += $$PWD/fcitxqtconnection.cpp \
$$PWD/fcitxqtformattedpreedit.cpp \
$$PWD/fcitxqtinputcontextproxy.cpp \
$$PWD/fcitxqtinputmethoditem.cpp \
$$PWD/fcitxqtinputmethodproxy.cpp \
$$PWD/fcitxqtkeyboardlayout.cpp \
$$PWD/fcitxqtkeyboardproxy.cpp \
$$PWD/keyuni.cpp \
$$PWD/main.cpp \
$$PWD/qfcitxplatforminputcontext.cpp \
$$PWD/utils.cpp
HEADERS += $$PWD/fcitxqtconnection.h \
$$PWD/fcitxqtconnection_p.h \
$$PWD/fcitxqtdbusaddons_export.h \
$$PWD/fcitxqtdbusaddons_version.h \
$$PWD/fcitxqtformattedpreedit.h \
$$PWD/fcitxqtinputcontextproxy.h \
$$PWD/fcitxqtinputmethoditem.h \
$$PWD/fcitxqtinputmethodproxy.h \
$$PWD/fcitxqtkeyboardlayout.h \
$$PWD/fcitxqtkeyboardproxy.h \
$$PWD/keydata.h \
$$PWD/keyserver_x11.h \
$$PWD/keyuni.h \
$$PWD/main.h \
$$PWD/qfcitxplatforminputcontext.h \
$$PWD/utils.h
OTHER_FILES += $$PWD/fcitx.json

View File

@@ -0,0 +1,369 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "fcitxqtconnection_p.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QDBusReply>
#include <QDBusConnectionInterface>
#include <QDebug>
#include <QFile>
#include <QTimer>
#include <QDir>
#include <signal.h>
#include <errno.h>
// utils function in fcitx-utils and fcitx-config
bool _pid_exists(pid_t pid) {
if (pid <= 0)
return 0;
return !(kill(pid, 0) && (errno == ESRCH));
}
FcitxQtConnection::FcitxQtConnection(QObject* parent): QObject(parent)
,d_ptr(new FcitxQtConnectionPrivate(this))
{
}
void FcitxQtConnection::startConnection()
{
Q_D(FcitxQtConnection);
if (!d->m_initialized) {
d->initialize();
d->createConnection();
}
}
void FcitxQtConnection::endConnection()
{
Q_D(FcitxQtConnection);
d->cleanUp();
d->finalize();
d->m_connectedOnce = false;
}
bool FcitxQtConnection::autoReconnect()
{
Q_D(FcitxQtConnection);
return d->m_autoReconnect;
}
void FcitxQtConnection::setAutoReconnect(bool a)
{
Q_D(FcitxQtConnection);
d->m_autoReconnect = a;
}
QDBusConnection* FcitxQtConnection::connection()
{
Q_D(FcitxQtConnection);
return d->m_connection;
}
const QString& FcitxQtConnection::serviceName()
{
Q_D(FcitxQtConnection);
return d->m_serviceName;
}
bool FcitxQtConnection::isConnected()
{
Q_D(FcitxQtConnection);
return d->isConnected();
}
FcitxQtConnection::~FcitxQtConnection()
{
}
FcitxQtConnectionPrivate::FcitxQtConnectionPrivate(FcitxQtConnection* conn) : QObject(conn)
,q_ptr(conn)
,m_displayNumber(-1)
,m_serviceName(QString("%1-%2").arg("org.fcitx.Fcitx").arg(displayNumber()))
,m_connection(0)
,m_serviceWatcher(new QDBusServiceWatcher(conn))
,m_watcher(new QFileSystemWatcher(this))
,m_autoReconnect(true)
,m_connectedOnce(false)
,m_initialized(false)
{
}
FcitxQtConnectionPrivate::~FcitxQtConnectionPrivate()
{
if (m_connection)
delete m_connection;
}
void FcitxQtConnectionPrivate::initialize() {
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->addWatchedService(m_serviceName);
QFileInfo info(socketFile());
QDir dir(info.path());
if (!dir.exists()) {
QDir rt(QDir::root());
rt.mkpath(info.path());
}
m_watcher->addPath(info.path());
if (info.exists()) {
m_watcher->addPath(info.filePath());
}
connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(socketFileChanged()));
connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(socketFileChanged()));
m_initialized = true;
}
void FcitxQtConnectionPrivate::finalize() {
m_serviceWatcher->removeWatchedService(m_serviceName);
m_watcher->removePaths(m_watcher->files());
m_watcher->removePaths(m_watcher->directories());
m_watcher->disconnect(SIGNAL(fileChanged(QString)));
m_watcher->disconnect(SIGNAL(directoryChanged(QString)));
m_initialized = false;
}
void FcitxQtConnectionPrivate::socketFileChanged() {
QFileInfo info(socketFile());
if (info.exists()) {
if (m_watcher->files().indexOf(info.filePath()) == -1)
m_watcher->addPath(info.filePath());
}
QString addr = address();
if (addr.isNull())
return;
cleanUp();
createConnection();
}
QByteArray FcitxQtConnectionPrivate::localMachineId()
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
return QDBusConnection::localMachineId();
#else
QFile file1("/var/lib/dbus/machine-id");
QFile file2("/etc/machine-id");
QFile* fileToRead = NULL;
if (file1.open(QIODevice::ReadOnly)) {
fileToRead = &file1;
}
else if (file2.open(QIODevice::ReadOnly)) {
fileToRead = &file2;
}
if (fileToRead) {
QByteArray result = fileToRead->readLine(1024);
fileToRead->close();
result = result.trimmed();
if (!result.isEmpty())
return result;
}
return "machine-id";
#endif
}
int FcitxQtConnectionPrivate::displayNumber() {
if (m_displayNumber < 0) {
QByteArray displayNumber("0");
QByteArray display(qgetenv("DISPLAY"));
int pos = display.indexOf(':');
if (pos >= 0) {
++pos;
int pos2 = display.indexOf('.', pos);
if (pos2 > 0) {
displayNumber = display.mid(pos, pos2 - pos);
} else {
displayNumber = display.mid(pos);
}
}
bool ok;
int d = displayNumber.toInt(&ok);
if (ok) {
m_displayNumber = d;
} else {
m_displayNumber = 0;
}
}
return m_displayNumber;
}
const QString& FcitxQtConnectionPrivate::socketFile()
{
if (!m_socketFile.isEmpty())
return m_socketFile;
QString filename = QString("%1-%2").arg(QString::fromLatin1(QDBusConnection::localMachineId())).arg(displayNumber());
QString home = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME"));
if (home.isEmpty()) {
home = QDir::homePath().append(QLatin1Literal("/.config"));
}
m_socketFile = QString("%1/fcitx/dbus/%2").arg(home).arg(filename);
return m_socketFile;
}
QString FcitxQtConnectionPrivate::address()
{
QString addr;
QByteArray addrVar = qgetenv("FCITX_DBUS_ADDRESS");
if (!addrVar.isNull())
return QString::fromLocal8Bit(addrVar);
QFile file(socketFile());
if (!file.open(QIODevice::ReadOnly))
return QString();
const int BUFSIZE = 1024;
char buffer[BUFSIZE];
size_t sz = file.read(buffer, BUFSIZE);
file.close();
if (sz == 0)
return QString();
char* p = buffer;
while(*p)
p++;
size_t addrlen = p - buffer;
if (sz != addrlen + 2 * sizeof(pid_t) + 1)
return QString();
/* skip '\0' */
p++;
pid_t *ppid = (pid_t*) p;
pid_t daemonpid = ppid[0];
pid_t fcitxpid = ppid[1];
if (!_pid_exists(daemonpid)
|| !_pid_exists(fcitxpid))
return QString();
addr = QLatin1String(buffer);
return addr;
}
void FcitxQtConnectionPrivate::createConnection() {
if (m_connectedOnce && !m_autoReconnect) {
return;
}
m_serviceWatcher->disconnect(SIGNAL(serviceOwnerChanged(QString,QString,QString)));
QString addr = address();
if (!addr.isNull()) {
QDBusConnection connection(QDBusConnection::connectToBus(addr, "fcitx"));
if (connection.isConnected()) {
// qDebug() << "create private";
m_connection = new QDBusConnection(connection);
}
else
QDBusConnection::disconnectFromBus("fcitx");
}
if (!m_connection) {
QDBusConnection* connection = new QDBusConnection(QDBusConnection::sessionBus());
connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(imChanged(QString,QString,QString)));
QDBusReply<bool> registered = connection->interface()->isServiceRegistered(m_serviceName);
if (!registered.isValid() || !registered.value()) {
delete connection;
}
else {
m_connection = connection;
}
}
Q_Q(FcitxQtConnection);
if (m_connection) {
m_connection->connect ("org.freedesktop.DBus.Local",
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local",
"Disconnected",
this,
SLOT (dbusDisconnected ()));
m_connectedOnce = true;
emit q->connected();
}
}
void FcitxQtConnectionPrivate::dbusDisconnected()
{
cleanUp();
createConnection();
}
void FcitxQtConnectionPrivate::imChanged(const QString& service, const QString& oldowner, const QString& newowner)
{
if (service == m_serviceName) {
/* old die */
if (oldowner.length() > 0 || newowner.length() > 0)
cleanUp();
/* new rise */
if (newowner.length() > 0) {
QTimer::singleShot(100, this, SLOT(newServiceAppear()));
}
}
}
void FcitxQtConnectionPrivate::cleanUp()
{
Q_Q(FcitxQtConnection);
bool doemit = false;
QDBusConnection::disconnectFromBus("fcitx");
if (m_connection) {
delete m_connection;
m_connection = 0;
doemit = true;
}
if (!m_autoReconnect && m_connectedOnce)
finalize();
/* we want m_connection and finalize being called before the signal
* thus isConnected will return false in slot
* and startConnection can be called in slot
*/
if (doemit)
emit q->disconnected();
}
bool FcitxQtConnectionPrivate::isConnected()
{
return m_connection && m_connection->isConnected();
}
void FcitxQtConnectionPrivate::newServiceAppear() {
if (!isConnected()) {
cleanUp();
createConnection();
}
}

View File

@@ -0,0 +1,111 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_H
#define FCITXQTCONNECTION_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QObject>
class QDBusConnection;
class FcitxQtConnectionPrivate;
/**
* dbus connection to fcitx
**/
class FCITXQTDBUSADDONS_EXPORT FcitxQtConnection : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
Q_PROPERTY(bool connected READ isConnected)
Q_PROPERTY(QDBusConnection* connection READ connection)
Q_PROPERTY(QString serviceName READ serviceName)
public:
/**
* create a new connection
*
* @param parent
**/
explicit FcitxQtConnection(QObject* parent = 0);
/**
* destroy the connection
**/
virtual ~FcitxQtConnection();
/**
* the connection will not start to work until you call this function
* you may want to connect to the signal before you call this function
**/
void startConnection();
void endConnection();
/**
* automatically reconnect if fcitx disappeared
*
* @param a ...
* @return void
**/
void setAutoReconnect(bool a);
/**
* check this connection is doing automatical reconnect or not
*
* default value is true
**/
bool autoReconnect();
/**
* return the current dbus connection to fcitx, notice, the object return
* by this function might be deteled if fcitx disappear, or might return 0
* if fcitx is not running
*
* @return QDBusConnection*
**/
QDBusConnection* connection();
/**
* current fcitx dbus service name, can be used for create DBus proxy
*
* @return service name
**/
const QString& serviceName();
/**
* check its connected or not
**/
bool isConnected();
Q_SIGNALS:
/**
* this signal will be emitted upon fcitx appears
**/
void connected();
/**
* this signal will be emitted upon fcitx disappears
*
* it will come with connected in pair
**/
void disconnected();
private:
FcitxQtConnectionPrivate * const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtConnection);
};
#endif // FCITXCONNECTION_H

View File

@@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_P_H
#define FCITXQTCONNECTION_P_H
#include "fcitxqtconnection.h"
#include <QtCore/QWeakPointer>
#include <QtCore/QFileSystemWatcher>
class QDBusConnection;
class QDBusServiceWatcher;
class FcitxQtConnectionPrivate : public QObject {
Q_OBJECT
public:
FcitxQtConnectionPrivate(FcitxQtConnection* conn);
virtual ~FcitxQtConnectionPrivate();
FcitxQtConnection * const q_ptr;
Q_DECLARE_PUBLIC(FcitxQtConnection);
private Q_SLOTS:
void imChanged(const QString& service, const QString& oldowner, const QString& newowner);
void dbusDisconnected();
void cleanUp();
void newServiceAppear();
void socketFileChanged();
private:
bool isConnected();
static QByteArray localMachineId();
const QString& socketFile();
void createConnection();
QString address();
int displayNumber();
void initialize();
void finalize();
int m_displayNumber;
QString m_serviceName;
QDBusConnection* m_connection;
QDBusServiceWatcher* m_serviceWatcher;
QFileSystemWatcher* m_watcher;
QString m_socketFile;
bool m_autoReconnect;
bool m_connectedOnce;
bool m_initialized;
};
#endif // FCITXCONNECTION_P_H

View File

@@ -0,0 +1,41 @@
#ifndef FCITXQTDBUSADDONS_EXPORT_H
#define FCITXQTDBUSADDONS_EXPORT_H
#ifdef FCITXQTDBUSADDONS_STATIC_DEFINE
# define FCITXQTDBUSADDONS_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT
#else
# ifndef FCITXQTDBUSADDONS_EXPORT
# ifdef FcitxQt5DBusAddons_EXPORTS
/* We are building this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# else
/* We are using this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# endif
# endif
# ifndef FCITXQTDBUSADDONS_NO_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT __attribute__((visibility("hidden")))
# endif
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED
# define FCITXQTDBUSADDONS_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_EXPORT FCITXQTDBUSADDONS_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT FCITXQTDBUSADDONS_NO_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#define DEFINE_NO_DEPRECATED 0
#if DEFINE_NO_DEPRECATED
# define FCITXQTDBUSADDONS_NO_DEPRECATED
#endif
#endif

View File

@@ -0,0 +1,11 @@
#ifndef FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_STRING "1.0.0"
#define FCITXQT5DBUSADDONS_VERSION_MAJOR 1
#define FCITXQT5DBUSADDONS_VERSION_MINOR 0
#define FCITXQT5DBUSADDONS_VERSION_PATCH 0
#define FCITXQT5DBUSADDONS_VERSION ((1<<16)|(0<<8)|(0))
#endif

View File

@@ -0,0 +1,78 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <QDBusMetaType>
#include "fcitxqtformattedpreedit.h"
void FcitxQtFormattedPreedit::registerMetaType()
{
qRegisterMetaType<FcitxQtFormattedPreedit>("FcitxQtFormattedPreedit");
qDBusRegisterMetaType<FcitxQtFormattedPreedit>();
qRegisterMetaType<FcitxQtFormattedPreeditList>("FcitxQtFormattedPreeditList");
qDBusRegisterMetaType<FcitxQtFormattedPreeditList>();
}
qint32 FcitxQtFormattedPreedit::format() const
{
return m_format;
}
const QString& FcitxQtFormattedPreedit::string() const
{
return m_string;
}
void FcitxQtFormattedPreedit::setFormat(qint32 format)
{
m_format = format;
}
void FcitxQtFormattedPreedit::setString(const QString& str)
{
m_string = str;
}
bool FcitxQtFormattedPreedit::operator==(const FcitxQtFormattedPreedit& preedit) const
{
return (preedit.m_format == m_format) && (preedit.m_string == m_string);
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& preedit)
{
argument.beginStructure();
argument << preedit.string();
argument << preedit.format();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& preedit)
{
QString str;
qint32 format;
argument.beginStructure();
argument >> str >> format;
argument.endStructure();
preedit.setString(str);
preedit.setFormat(format);
return argument;
}

View File

@@ -0,0 +1,51 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_FORMATTED_PREEDIT_H
#define FCITX_QT_FORMATTED_PREEDIT_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtFormattedPreedit {
public:
const QString& string() const;
qint32 format() const;
void setString(const QString& str);
void setFormat(qint32 format);
static void registerMetaType();
bool operator ==(const FcitxQtFormattedPreedit& preedit) const;
private:
QString m_string;
qint32 m_format;
};
typedef QList<FcitxQtFormattedPreedit> FcitxQtFormattedPreeditList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& im);
Q_DECLARE_METATYPE(FcitxQtFormattedPreedit)
Q_DECLARE_METATYPE(FcitxQtFormattedPreeditList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputcontextproxy.h"
/*
* Implementation of interface class FcitxQtInputContextProxy
*/
FcitxQtInputContextProxy::FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputContextProxy::~FcitxQtInputContextProxy()
{
}

View File

@@ -0,0 +1,136 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTCONTEXTPROXY_H_1409252990
#define FCITXQTINPUTCONTEXTPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtformattedpreedit.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputContextProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputContext"; }
public:
FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputContextProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CloseIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CloseIC"), argumentList);
}
inline QDBusPendingReply<> DestroyIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("DestroyIC"), argumentList);
}
inline QDBusPendingReply<> EnableIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("EnableIC"), argumentList);
}
inline QDBusPendingReply<> FocusIn()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusIn"), argumentList);
}
inline QDBusPendingReply<> FocusOut()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusOut"), argumentList);
}
inline QDBusPendingReply<> MouseEvent(int x)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x);
return asyncCallWithArgumentList(QLatin1String("MouseEvent"), argumentList);
}
inline QDBusPendingReply<int> ProcessKeyEvent(uint keyval, uint keycode, uint state, int type, uint time)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval) << QVariant::fromValue(keycode) << QVariant::fromValue(state) << QVariant::fromValue(type) << QVariant::fromValue(time);
return asyncCallWithArgumentList(QLatin1String("ProcessKeyEvent"), argumentList);
}
inline QDBusPendingReply<> Reset()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapacity(uint caps)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QLatin1String("SetCapacity"), argumentList);
}
inline QDBusPendingReply<> SetCursorLocation(int x, int y)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y);
return asyncCallWithArgumentList(QLatin1String("SetCursorLocation"), argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QLatin1String("SetCursorRect"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text, uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CloseIM();
void CommitString(const QString &str);
void DeleteSurroundingText(int offset, uint nchar);
void EnableIM();
void ForwardKey(uint keyval, uint state, int type);
void UpdateClientSideUI(const QString &auxup, const QString &auxdown, const QString &preedit, const QString &candidateword, const QString &imname, int cursorpos);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
};
#endif

View File

@@ -0,0 +1,95 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtinputmethoditem.h"
bool FcitxQtInputMethodItem::enabled() const
{
return m_enabled;
}
const QString& FcitxQtInputMethodItem::langCode() const
{
return m_langCode;
}
const QString& FcitxQtInputMethodItem::name() const
{
return m_name;
}
const QString& FcitxQtInputMethodItem::uniqueName() const
{
return m_uniqueName;
}
void FcitxQtInputMethodItem::setEnabled(bool enable)
{
m_enabled = enable;
}
void FcitxQtInputMethodItem::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtInputMethodItem::setName(const QString& name)
{
m_name = name;
}
void FcitxQtInputMethodItem::setUniqueName(const QString& name)
{
m_uniqueName = name;
}
void FcitxQtInputMethodItem::registerMetaType()
{
qRegisterMetaType<FcitxQtInputMethodItem>("FcitxQtInputMethodItem");
qDBusRegisterMetaType<FcitxQtInputMethodItem>();
qRegisterMetaType<FcitxQtInputMethodItemList>("FcitxQtInputMethodItemList");
qDBusRegisterMetaType<FcitxQtInputMethodItemList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im)
{
argument.beginStructure();
argument << im.name();
argument << im.uniqueName();
argument << im.langCode();
argument << im.enabled();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im)
{
QString name;
QString uniqueName;
QString langCode;
bool enabled;
argument.beginStructure();
argument >> name >> uniqueName >> langCode >> enabled;
argument.endStructure();
im.setName(name);
im.setUniqueName(uniqueName);
im.setLangCode(langCode);
im.setEnabled(enabled);
return argument;
}

View File

@@ -0,0 +1,64 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_INPUT_METHOD_ITEM_H
#define FCITX_QT_INPUT_METHOD_ITEM_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodItem
{
public:
const QString& name() const;
const QString& uniqueName() const;
const QString& langCode() const;
bool enabled() const;
void setName(const QString& name);
void setUniqueName(const QString& name);
void setLangCode(const QString& name);
void setEnabled(bool name);
static void registerMetaType();
inline bool operator < (const FcitxQtInputMethodItem& im) const {
if (m_enabled == true && im.m_enabled == false)
return true;
return false;
}
private:
QString m_name;
QString m_uniqueName;
QString m_langCode;
bool m_enabled;
};
typedef QList<FcitxQtInputMethodItem> FcitxQtInputMethodItemList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im);
Q_DECLARE_METATYPE(FcitxQtInputMethodItem)
Q_DECLARE_METATYPE(FcitxQtInputMethodItemList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputmethodproxy.h"
/*
* Implementation of interface class FcitxQtInputMethodProxy
*/
FcitxQtInputMethodProxy::FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputMethodProxy::~FcitxQtInputMethodProxy()
{
}

View File

@@ -0,0 +1,217 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTMETHODPROXY_H_1409252990
#define FCITXQTINPUTMETHODPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtinputmethoditem.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputMethod
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputMethod"; }
public:
FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputMethodProxy();
Q_PROPERTY(QString CurrentIM READ currentIM WRITE setCurrentIM)
inline QString currentIM() const
{ return qvariant_cast< QString >(property("CurrentIM")); }
inline void setCurrentIM(const QString &value)
{ setProperty("CurrentIM", QVariant::fromValue(value)); }
Q_PROPERTY(FcitxQtInputMethodItemList IMList READ iMList WRITE setIMList)
inline FcitxQtInputMethodItemList iMList() const
{ return qvariant_cast< FcitxQtInputMethodItemList >(property("IMList")); }
inline void setIMList(FcitxQtInputMethodItemList value)
{ setProperty("IMList", QVariant::fromValue(value)); }
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> ActivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ActivateIM"), argumentList);
}
inline QDBusPendingReply<> Configure()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Configure"), argumentList);
}
inline QDBusPendingReply<> ConfigureAddon(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ConfigureAddon"), argumentList);
}
inline QDBusPendingReply<> ConfigureIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("ConfigureIM"), argumentList);
}
inline QDBusPendingReply<int, uint, uint, uint, uint> CreateIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CreateIC"), argumentList);
}
inline QDBusReply<int> CreateIC(uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateIC"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 5) {
keyval1 = qdbus_cast<uint>(reply.arguments().at(1));
state1 = qdbus_cast<uint>(reply.arguments().at(2));
keyval2 = qdbus_cast<uint>(reply.arguments().at(3));
state2 = qdbus_cast<uint>(reply.arguments().at(4));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv2(const QString &appname)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
return asyncCallWithArgumentList(QLatin1String("CreateICv2"), argumentList);
}
inline QDBusReply<int> CreateICv2(const QString &appname, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv2"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv3(const QString &appname, int pid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
return asyncCallWithArgumentList(QLatin1String("CreateICv3"), argumentList);
}
inline QDBusReply<int> CreateICv3(const QString &appname, int pid, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv3"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<> Exit()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Exit"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentIM"), argumentList);
}
inline QDBusPendingReply<int> GetCurrentState()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentState"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentUI()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentUI"), argumentList);
}
inline QDBusPendingReply<QString> GetIMAddon(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetIMAddon"), argumentList);
}
inline QDBusPendingReply<> InactivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("InactivateIM"), argumentList);
}
inline QDBusPendingReply<> ReloadAddonConfig(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ReloadAddonConfig"), argumentList);
}
inline QDBusPendingReply<> ReloadConfig()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ReloadConfig"), argumentList);
}
inline QDBusPendingReply<> ResetIMList()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ResetIMList"), argumentList);
}
inline QDBusPendingReply<> Restart()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Restart"), argumentList);
}
inline QDBusPendingReply<> SetCurrentIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("SetCurrentIM"), argumentList);
}
inline QDBusPendingReply<> ToggleIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ToggleIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View File

@@ -0,0 +1,100 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtkeyboardlayout.h"
const QString& FcitxQtKeyboardLayout::layout() const
{
return m_layout;
}
const QString& FcitxQtKeyboardLayout::langCode() const
{
return m_langCode;
}
const QString& FcitxQtKeyboardLayout::name() const
{
return m_name;
}
const QString& FcitxQtKeyboardLayout::variant() const
{
return m_variant;
}
void FcitxQtKeyboardLayout::setLayout(const QString& layout)
{
m_layout = layout;
}
void FcitxQtKeyboardLayout::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtKeyboardLayout::setName(const QString& name)
{
m_name = name;
}
void FcitxQtKeyboardLayout::setVariant(const QString& variant)
{
m_variant = variant;
}
void FcitxQtKeyboardLayout::registerMetaType()
{
qRegisterMetaType<FcitxQtKeyboardLayout>("FcitxQtKeyboardLayout");
qDBusRegisterMetaType<FcitxQtKeyboardLayout>();
qRegisterMetaType<FcitxQtKeyboardLayoutList>("FcitxQtKeyboardLayoutList");
qDBusRegisterMetaType<FcitxQtKeyboardLayoutList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& layout)
{
argument.beginStructure();
argument << layout.layout();
argument << layout.variant();
argument << layout.name();
argument << layout.langCode();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& layout)
{
QString l;
QString variant;
QString name;
QString langCode;
argument.beginStructure();
argument >> l >> variant >> name >> langCode;
argument.endStructure();
layout.setLayout(l);
layout.setVariant(variant);
layout.setName(name);
layout.setLangCode(langCode);
return argument;
}

View File

@@ -0,0 +1,58 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_KEYBOARD_LAYOUT_H
#define FCITX_QT_KEYBOARD_LAYOUT_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardLayout
{
public:
const QString& layout() const;
const QString& variant() const;
const QString& name() const;
const QString& langCode() const;
void setLayout(const QString& layout);
void setLangCode(const QString& lang);
void setName(const QString& name);
void setVariant(const QString& variant);
static void registerMetaType();
private:
QString m_layout;
QString m_variant;
QString m_name;
QString m_langCode;
};
typedef QList<FcitxQtKeyboardLayout> FcitxQtKeyboardLayoutList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& l);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& l);
Q_DECLARE_METATYPE(FcitxQtKeyboardLayout)
Q_DECLARE_METATYPE(FcitxQtKeyboardLayoutList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtkeyboardproxy.h"
/*
* Implementation of interface class FcitxQtKeyboardProxy
*/
FcitxQtKeyboardProxy::FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtKeyboardProxy::~FcitxQtKeyboardProxy()
{
}

View File

@@ -0,0 +1,74 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTKEYBOARDPROXY_H_1409252990
#define FCITXQTKEYBOARDPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtkeyboardlayout.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.Keyboard
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.Keyboard"; }
public:
FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtKeyboardProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QString, QString> GetLayoutForIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetLayoutForIM"), argumentList);
}
inline QDBusReply<QString> GetLayoutForIM(const QString &im, QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("GetLayoutForIM"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
variant = qdbus_cast<QString>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<FcitxQtKeyboardLayoutList> GetLayouts()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetLayouts"), argumentList);
}
inline QDBusPendingReply<> SetLayoutForIM(const QString &im, const QString &layout, const QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im) << QVariant::fromValue(layout) << QVariant::fromValue(variant);
return asyncCallWithArgumentList(QLatin1String("SetLayoutForIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View File

@@ -0,0 +1,81 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputContext">
<method name="EnableIC">
</method>
<method name="CloseIC">
</method>
<method name="FocusIn">
</method>
<method name="FocusOut">
</method>
<method name="Reset">
</method>
<method name="MouseEvent">
<arg name="x" direction="in" type="i" />
</method>
<method name="SetCursorLocation">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
</method>
<method name="SetCursorRect">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
<arg name="w" direction="in" type="i"/>
<arg name="h" direction="in" type="i"/>
</method>
<method name="SetCapacity">
<arg name="caps" direction="in" type="u"/>
</method>
<method name="SetSurroundingText">
<arg name="text" direction="in" type="s"/>
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="SetSurroundingTextPosition">
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="DestroyIC">
</method>
<method name="ProcessKeyEvent">
<arg name="keyval" direction="in" type="u"/>
<arg name="keycode" direction="in" type="u"/>
<arg name="state" direction="in" type="u"/>
<arg name="type" direction="in" type="i"/>
<arg name="time" direction="in" type="u"/>
<arg name="ret" direction="out" type="i"/>
</method>
<signal name="EnableIM">
</signal>
<signal name="CloseIM">
</signal>
<signal name="CommitString">
<arg name="str" type="s"/>
</signal>
<signal name="UpdateFormattedPreedit">
<arg name="str" type="a(si)" />
<arg name="cursorpos" type="i"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
</signal>
<signal name="UpdateClientSideUI">
<arg name="auxup" type="s"/>
<arg name="auxdown" type="s"/>
<arg name="preedit" type="s"/>
<arg name="candidateword" type="s"/>
<arg name="imname" type="s"/>
<arg name="cursorpos" type="i"/>
</signal>
<signal name="ForwardKey">
<arg name="keyval" type="u"/>
<arg name="state" type="u"/>
<arg name="type" type="i"/>
</signal>
<signal name="DeleteSurroundingText">
<arg name="offset" type="i"/>
<arg name="nchar" type="u"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,81 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputMethod">
<method name="CreateIC">
<arg name="icid" direction="out" type="i"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv2">
<arg name="appname" direction="in" type="s"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv3">
<arg name="appname" direction="in" type="s"/>
<arg name="pid" direction="in" type="i"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="Exit">
</method>
<method name="GetCurrentIM">
<arg name="im" direction="out" type="s"/>
</method>
<method name="SetCurrentIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="ReloadConfig">
</method>
<method name="ReloadAddonConfig">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="Restart">
</method>
<method name="Configure">
</method>
<method name="ConfigureAddon">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="ConfigureIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="GetCurrentUI">
<arg name="addon" direction="out" type="s"/>
</method>
<method name="GetIMAddon">
<arg name="im" direction="in" type="s"/>
<arg name="addon" direction="out" type="s"/>
</method>
<method name="ActivateIM">
</method>
<method name="InactivateIM">
</method>
<method name="ToggleIM">
</method>
<method name="ResetIMList">
</method>
<method name="GetCurrentState">
<arg name="state" direction="out" type="i"/>
</method>
<property access="readwrite" type="a(sssb)" name="IMList">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
<annotation name="com.trolltech.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
<annotation name="org.qtproject.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
</property>
<property access="readwrite" type="s" name="CurrentIM">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
</interface>
</node>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.Keyboard">
<method name="GetLayouts">
<arg name="layouts" direction="out" type="a(ssss)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
</method>
<method name="GetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="out" type="s"/>
<arg name="variant" direction="out" type="s"/>
</method>
<method name="SetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="in" type="s"/>
<arg name="variant" direction="in" type="s"/>
</method>
</interface>
</node>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
/*
Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
Win32 port:
Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KEYSERVER_X11_H
#define KEYSERVER_X11_H
#include <X11/keysym.h>
struct TransKey {
int keySymQt;
uint keySymX;
};
static const TransKey g_rgQtToSymX[] = {
{ Qt::Key_Escape, XK_Escape },
{ Qt::Key_Tab, XK_Tab },
{ Qt::Key_Backtab, XK_ISO_Left_Tab },
{ Qt::Key_Backspace, XK_BackSpace },
{ Qt::Key_Return, XK_Return },
{ Qt::Key_Enter, XK_KP_Enter },
{ Qt::Key_Insert, XK_Insert },
{ Qt::Key_Delete, XK_Delete },
{ Qt::Key_Pause, XK_Pause },
#ifdef sun
{ Qt::Key_Print, XK_F22 },
#else
{ Qt::Key_Print, XK_Print },
#endif
{ Qt::Key_SysReq, XK_Sys_Req },
{ Qt::Key_Home, XK_Home },
{ Qt::Key_End, XK_End },
{ Qt::Key_Left, XK_Left },
{ Qt::Key_Up, XK_Up },
{ Qt::Key_Right, XK_Right },
{ Qt::Key_Down, XK_Down },
//{ Qt::Key_Shift, 0 },
//{ Qt::Key_Control, 0 },
//{ Qt::Key_Meta, 0 },
//{ Qt::Key_Alt, 0 },
{ Qt::Key_CapsLock, XK_Caps_Lock },
{ Qt::Key_NumLock, XK_Num_Lock },
{ Qt::Key_ScrollLock, XK_Scroll_Lock },
{ Qt::Key_F1, XK_F1 },
{ Qt::Key_F2, XK_F2 },
{ Qt::Key_F3, XK_F3 },
{ Qt::Key_F4, XK_F4 },
{ Qt::Key_F5, XK_F5 },
{ Qt::Key_F6, XK_F6 },
{ Qt::Key_F7, XK_F7 },
{ Qt::Key_F8, XK_F8 },
{ Qt::Key_F9, XK_F9 },
{ Qt::Key_F10, XK_F10 },
{ Qt::Key_F11, XK_F11 },
{ Qt::Key_F12, XK_F12 },
{ Qt::Key_F13, XK_F13 },
{ Qt::Key_F14, XK_F14 },
{ Qt::Key_F15, XK_F15 },
{ Qt::Key_F16, XK_F16 },
{ Qt::Key_F17, XK_F17 },
{ Qt::Key_F18, XK_F18 },
{ Qt::Key_F19, XK_F19 },
{ Qt::Key_F20, XK_F20 },
{ Qt::Key_F21, XK_F21 },
{ Qt::Key_F22, XK_F22 },
{ Qt::Key_F23, XK_F23 },
{ Qt::Key_F24, XK_F24 },
{ Qt::Key_F25, XK_F25 },
{ Qt::Key_F26, XK_F26 },
{ Qt::Key_F27, XK_F27 },
{ Qt::Key_F28, XK_F28 },
{ Qt::Key_F29, XK_F29 },
{ Qt::Key_F30, XK_F30 },
{ Qt::Key_F31, XK_F31 },
{ Qt::Key_F32, XK_F32 },
{ Qt::Key_F33, XK_F33 },
{ Qt::Key_F34, XK_F34 },
{ Qt::Key_F35, XK_F35 },
{ Qt::Key_Super_L, XK_Super_L },
{ Qt::Key_Super_R, XK_Super_R },
{ Qt::Key_Menu, XK_Menu },
{ Qt::Key_Hyper_L, XK_Hyper_L },
{ Qt::Key_Hyper_R, XK_Hyper_R },
{ Qt::Key_Help, XK_Help },
{ '/', XK_KP_Divide },
{ '*', XK_KP_Multiply },
{ '-', XK_KP_Subtract },
{ '+', XK_KP_Add },
{ Qt::Key_Return, XK_KP_Enter },
{Qt::Key_Multi_key, XK_Multi_key},
{Qt::Key_Codeinput, XK_Codeinput},
{Qt::Key_SingleCandidate, XK_SingleCandidate},
{Qt::Key_MultipleCandidate, XK_MultipleCandidate},
{Qt::Key_PreviousCandidate, XK_PreviousCandidate},
{Qt::Key_Mode_switch, XK_Mode_switch},
{Qt::Key_Kanji, XK_Kanji},
{Qt::Key_Muhenkan, XK_Muhenkan},
{Qt::Key_Henkan, XK_Henkan},
{Qt::Key_Romaji, XK_Romaji},
{Qt::Key_Hiragana, XK_Hiragana},
{Qt::Key_Katakana, XK_Katakana},
{Qt::Key_Hiragana_Katakana, XK_Hiragana_Katakana},
{Qt::Key_Zenkaku, XK_Zenkaku},
{Qt::Key_Hankaku, XK_Hankaku},
{Qt::Key_Zenkaku_Hankaku, XK_Zenkaku_Hankaku},
{Qt::Key_Touroku, XK_Touroku},
{Qt::Key_Massyo, XK_Massyo},
{Qt::Key_Kana_Lock, XK_Kana_Lock},
{Qt::Key_Kana_Shift, XK_Kana_Shift},
{Qt::Key_Eisu_Shift, XK_Eisu_Shift},
{Qt::Key_Eisu_toggle, XK_Eisu_toggle},
{Qt::Key_Hangul, XK_Hangul},
{Qt::Key_Hangul_Start, XK_Hangul_Start},
{Qt::Key_Hangul_End, XK_Hangul_End},
{Qt::Key_Hangul_Hanja, XK_Hangul_Hanja},
{Qt::Key_Hangul_Jamo, XK_Hangul_Jamo},
{Qt::Key_Hangul_Romaja, XK_Hangul_Romaja},
{Qt::Key_Hangul_Jeonja, XK_Hangul_Jeonja},
{Qt::Key_Hangul_Banja, XK_Hangul_Banja},
{Qt::Key_Hangul_PreHanja, XK_Hangul_PreHanja},
{Qt::Key_Hangul_PostHanja, XK_Hangul_PostHanja},
{Qt::Key_Hangul_Special, XK_Hangul_Special},
};
#include <qstring.h>
inline int map_sym_to_qt(uint keySym)
{
if (keySym < 0x1000) {
if (keySym >= 'a' && keySym <= 'z')
return QChar(keySym).toUpper().unicode();
return keySym;
}
#ifdef Q_WS_WIN
if (keySym < 0x3000)
return keySym;
#else
if (keySym < 0x3000)
return keySym | Qt::UNICODE_ACCEL;
for (uint i = 0; i < sizeof(g_rgQtToSymX) / sizeof(TransKey); i++)
if (g_rgQtToSymX[i].keySymX == keySym)
return g_rgQtToSymX[i].keySymQt;
#endif
return Qt::Key_unknown;
}
static bool symToKeyQt(uint keySym, int& keyQt)
{
keyQt = map_sym_to_qt(keySym);
return (keyQt != Qt::Key_unknown);
}
#endif

View File

@@ -0,0 +1,56 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <stdint.h>
#include "keyuni.h"
#include "keydata.h"
uint32_t
FcitxKeySymToUnicode (uint32_t keyval)
{
int min = 0;
int max = sizeof (gdk_keysym_to_unicode_tab) / sizeof(gdk_keysym_to_unicode_tab[0]) - 1;
int mid;
/* First check for Latin-1 characters (1:1 mapping) */
if ((keyval >= 0x0020 && keyval <= 0x007e) ||
(keyval >= 0x00a0 && keyval <= 0x00ff))
return keyval;
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((keyval & 0xff000000) == 0x01000000)
return keyval & 0x00ffffff;
/* binary search in table */
while (max >= min) {
mid = (min + max) / 2;
if (gdk_keysym_to_unicode_tab[mid].keysym < keyval)
min = mid + 1;
else if (gdk_keysym_to_unicode_tab[mid].keysym > keyval)
max = mid - 1;
else {
/* found it */
return gdk_keysym_to_unicode_tab[mid].ucs;
}
}
/* No matching Unicode value found */
return 0;
}

View File

@@ -0,0 +1,29 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef KEYUNI_H
#define KEYUNI_H
#include <qglobal.h>
quint32
FcitxKeySymToUnicode (quint32 keyval);
#endif // KEYUNI_H

View File

@@ -0,0 +1,35 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "main.h"
QStringList QFcitxPlatformInputContextPlugin::keys() const
{
return QStringList(QStringLiteral("fcitx"));
}
QFcitxPlatformInputContext *QFcitxPlatformInputContextPlugin::create(const QString& system, const QStringList& paramList)
{
Q_UNUSED(paramList);
if (system.compare(system, QStringLiteral("fcitx"), Qt::CaseInsensitive) == 0)
return new QFcitxPlatformInputContext;
return 0;
}

View File

@@ -0,0 +1,37 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef MAIN_H
#define MAIN_H
#include <qpa/qplatforminputcontextplugin_p.h>
#include <QtCore/QStringList>
#include "qfcitxplatforminputcontext.h"
class QFcitxPlatformInputContextPlugin : public QPlatformInputContextPlugin
{
Q_OBJECT
public:
Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "fcitx.json")
QStringList keys() const;
QFcitxPlatformInputContext *create(const QString& system, const QStringList& paramList);
};
#endif // MAIN_H

View File

@@ -0,0 +1,770 @@
/***************************************************************************
* Copyright (C) 2011~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <QKeyEvent>
#include <QDBusConnection>
#include <QGuiApplication>
#include <QInputMethod>
#include <QTextCharFormat>
#include <QPalette>
#include <QWindow>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformcursor.h>
#include <qpa/qwindowsysteminterface.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include "keyserver_x11.h"
#include "qfcitxplatforminputcontext.h"
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtconnection.h"
#include "keyuni.h"
#include "utils.h"
static bool key_filtered = false;
static bool
get_boolean_env(const char *name,
bool defval)
{
const char *value = getenv(name);
if (value == NULL)
return defval;
if (strcmp(value, "") == 0 ||
strcmp(value, "0") == 0 ||
strcmp(value, "false") == 0 ||
strcmp(value, "False") == 0 ||
strcmp(value, "FALSE") == 0)
return false;
return true;
}
static inline const char*
get_locale()
{
const char* locale = getenv("LC_ALL");
if (!locale)
locale = getenv("LC_CTYPE");
if (!locale)
locale = getenv("LANG");
if (!locale)
locale = "C";
return locale;
}
struct xkb_context* _xkb_context_new_helper()
{
struct xkb_context* context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (context) {
xkb_context_set_log_level(context, XKB_LOG_LEVEL_CRITICAL);
}
return context;
}
QFcitxPlatformInputContext::QFcitxPlatformInputContext() :
m_connection(new FcitxQtConnection(this)),
m_improxy(0),
m_n_compose(0),
m_cursorPos(0),
m_useSurroundingText(false),
m_syncMode(true),
m_lastWId(0),
m_destroy(false),
m_xkbContext(_xkb_context_new_helper()),
m_xkbComposeTable(m_xkbContext ? xkb_compose_table_new_from_locale(m_xkbContext.data(), get_locale(), XKB_COMPOSE_COMPILE_NO_FLAGS) : 0),
m_xkbComposeState(m_xkbComposeTable ? xkb_compose_state_new(m_xkbComposeTable.data(), XKB_COMPOSE_STATE_NO_FLAGS) : 0)
{
FcitxQtFormattedPreedit::registerMetaType();
memset(m_compose_buffer, 0, sizeof(uint) * (MAX_COMPOSE_LEN + 1));
connect(m_connection, SIGNAL(connected()), this, SLOT(connected()));
connect(m_connection, SIGNAL(disconnected()), this, SLOT(cleanUp()));
m_connection->startConnection();
}
QFcitxPlatformInputContext::~QFcitxPlatformInputContext()
{
m_destroy = true;
cleanUp();
}
void QFcitxPlatformInputContext::connected()
{
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->name();
if (m_improxy) {
delete m_improxy;
m_improxy = 0;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(), QLatin1String("/inputmethod"), *m_connection->connection(), this);
QWindow* w = qApp->focusWindow();
if (w)
createICData(w);
}
void QFcitxPlatformInputContext::cleanUp()
{
for(QHash<WId, FcitxQtICData *>::const_iterator i = m_icMap.constBegin(),
e = m_icMap.constEnd(); i != e; ++i) {
FcitxQtICData* data = i.value();
if (data->proxy)
delete data->proxy;
}
m_icMap.clear();
if (m_improxy) {
delete m_improxy;
m_improxy = 0;
}
if (!m_destroy) {
commitPreedit();
}
}
bool QFcitxPlatformInputContext::isValid() const
{
return true;
}
void QFcitxPlatformInputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
{
if (action == QInputMethod::Click
&& (cursorPosition <= 0 || cursorPosition >= m_preedit.length())
)
{
// qDebug() << action << cursorPosition;
commitPreedit();
}
}
void QFcitxPlatformInputContext::commitPreedit()
{
QObject *input = qApp->focusObject();
if (!input)
return;
if (m_commitPreedit.length() <= 0)
return;
QInputMethodEvent e;
e.setCommitString(m_commitPreedit);
QCoreApplication::sendEvent(input, &e);
m_commitPreedit.clear();
}
void QFcitxPlatformInputContext::reset()
{
commitPreedit();
FcitxQtInputContextProxy* proxy = validIC();
if (proxy)
proxy->Reset();
if (m_xkbComposeState) {
xkb_compose_state_reset(m_xkbComposeState.data());
}
QPlatformInputContext::reset();
}
void QFcitxPlatformInputContext::update(Qt::InputMethodQueries queries )
{
QWindow* window = qApp->focusWindow();
FcitxQtInputContextProxy* proxy = validICByWindow(window);
if (!proxy)
return;
FcitxQtICData* data = m_icMap.value(window->winId());
QInputMethod *method = qApp->inputMethod();
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodQueryEvent query(queries);
QGuiApplication::sendEvent(input, &query);
if (queries & Qt::ImCursorRectangle) {
cursorRectChanged();
}
if (queries & Qt::ImHints) {
Qt::InputMethodHints hints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt());
#define CHECK_HINTS(_HINTS, _CAPACITY) \
if (hints & _HINTS) \
addCapacity(data, _CAPACITY); \
else \
removeCapacity(data, _CAPACITY);
CHECK_HINTS(Qt::ImhNoAutoUppercase, CAPACITY_NOAUTOUPPERCASE)
CHECK_HINTS(Qt::ImhPreferNumbers, CAPACITY_NUMBER)
CHECK_HINTS(Qt::ImhPreferUppercase, CAPACITY_UPPERCASE)
CHECK_HINTS(Qt::ImhPreferLowercase, CAPACITY_LOWERCASE)
CHECK_HINTS(Qt::ImhNoPredictiveText, CAPACITY_NO_SPELLCHECK)
CHECK_HINTS(Qt::ImhDigitsOnly, CAPACITY_DIGIT)
CHECK_HINTS(Qt::ImhFormattedNumbersOnly, CAPACITY_NUMBER)
CHECK_HINTS(Qt::ImhUppercaseOnly, CAPACITY_UPPERCASE)
CHECK_HINTS(Qt::ImhLowercaseOnly, CAPACITY_LOWERCASE)
CHECK_HINTS(Qt::ImhDialableCharactersOnly, CAPACITY_DIALABLE)
CHECK_HINTS(Qt::ImhEmailCharactersOnly, CAPACITY_EMAIL)
}
bool setSurrounding = false;
do {
if (!m_useSurroundingText)
break;
if (!((queries & Qt::ImSurroundingText) && (queries & Qt::ImCursorPosition)))
break;
if (data->capacity.testFlag(CAPACITY_PASSWORD))
break;
QVariant var = query.value(Qt::ImSurroundingText);
QVariant var1 = query.value(Qt::ImCursorPosition);
QVariant var2 = query.value(Qt::ImAnchorPosition);
if (!var.isValid() || !var1.isValid())
break;
QString text = var.toString();
/* we don't want to waste too much memory here */
#define SURROUNDING_THRESHOLD 4096
if (text.length() < SURROUNDING_THRESHOLD) {
if (_utf8_check_string(text.toUtf8().data())) {
addCapacity(data, CAPACITY_SURROUNDING_TEXT);
int cursor = var1.toInt();
int anchor;
if (var2.isValid())
anchor = var2.toInt();
else
anchor = cursor;
if (data->surroundingText != text) {
data->surroundingText = text;
proxy->SetSurroundingText(text, cursor, anchor);
}
else {
if (data->surroundingAnchor != anchor ||
data->surroundingCursor != cursor)
proxy->SetSurroundingTextPosition(cursor, anchor);
}
data->surroundingCursor = cursor;
data->surroundingAnchor = anchor;
setSurrounding = true;
}
}
if (!setSurrounding) {
data->surroundingAnchor = -1;
data->surroundingCursor = -1;
data->surroundingText = QString::null;
removeCapacity(data, CAPACITY_SURROUNDING_TEXT);
}
} while(0);
}
void QFcitxPlatformInputContext::commit()
{
QPlatformInputContext::commit();
}
void QFcitxPlatformInputContext::setFocusObject(QObject* object)
{
FcitxQtInputContextProxy* proxy = validICByWId(m_lastWId);
if (proxy) {
proxy->FocusOut();
}
QWindow *window = qApp->focusWindow();
if (window) {
m_lastWId = window->winId();
} else {
m_lastWId = 0;
return;
}
proxy = validICByWindow(window);
if (proxy)
proxy->FocusIn();
else {
FcitxQtICData* data = m_icMap.value(window->winId());
if (!data) {
createICData(window);
return;
}
}
}
void QFcitxPlatformInputContext::windowDestroyed(QObject* object)
{
/* access QWindow is not possible here, so we use our own map to do so */
WId wid = m_windowToWidMap.take(object);
if (!wid)
return;
FcitxQtICData* data = m_icMap.take(wid);
if (!data)
return;
delete data;
// qDebug() << "Window Destroyed and we destroy IC correctly, horray!";
}
void QFcitxPlatformInputContext::cursorRectChanged()
{
QWindow *inputWindow = qApp->focusWindow();
if (!inputWindow)
return;
FcitxQtInputContextProxy* proxy = validICByWindow(inputWindow);
if (!proxy)
return;
FcitxQtICData* data = m_icMap.value(inputWindow->winId());
QRect r = qApp->inputMethod()->cursorRectangle().toRect();
if(!r.isValid())
return;
r.moveTopLeft(inputWindow->mapToGlobal(r.topLeft()));
qreal scale = inputWindow->devicePixelRatio();
if (data->rect != r) {
data->rect = r;
proxy->SetCursorRect(r.x() * scale, r.y() * scale,
r.width() * scale, r.height() * scale);
}
}
void QFcitxPlatformInputContext::createInputContext(WId w)
{
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->connection()->name();
if (m_improxy) {
delete m_improxy;
m_improxy = NULL;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(), QLatin1String("/inputmethod"), *m_connection->connection(), this);
if (!m_improxy->isValid())
return;
QFileInfo info(QCoreApplication::applicationFilePath());
QDBusPendingReply< int, bool, uint, uint, uint, uint > result = m_improxy->CreateICv3(info.fileName(), QCoreApplication::applicationPid());
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(result);
watcher->setProperty("wid", (qulonglong) w);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(createInputContextFinished(QDBusPendingCallWatcher*)));
}
void QFcitxPlatformInputContext::createInputContextFinished(QDBusPendingCallWatcher* watcher)
{
WId w = watcher->property("wid").toULongLong();
FcitxQtICData* data = m_icMap.value(w);
if (!data)
return;
QDBusPendingReply< int, bool, uint, uint, uint, uint > result = *watcher;
do {
if (result.isError()) {
break;
}
if (!m_connection->isConnected())
break;
int id = qdbus_cast<int>(result.argumentAt(0));
QString path = QString("/inputcontext_%1").arg(id);
if (data->proxy) {
delete data->proxy;
}
data->proxy = new FcitxQtInputContextProxy(m_connection->serviceName(), path, *m_connection->connection(), this);
connect(data->proxy, SIGNAL(CommitString(QString)), this, SLOT(commitString(QString)));
connect(data->proxy, SIGNAL(ForwardKey(uint, uint, int)), this, SLOT(forwardKey(uint, uint, int)));
connect(data->proxy, SIGNAL(UpdateFormattedPreedit(FcitxQtFormattedPreeditList,int)), this, SLOT(updateFormattedPreedit(FcitxQtFormattedPreeditList,int)));
connect(data->proxy, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
if (data->proxy->isValid()) {
QWindow* window = qApp->focusWindow();
if (window && window->winId() == w)
data->proxy->FocusIn();
}
QFlags<FcitxCapacityFlags> flag;
flag |= CAPACITY_PREEDIT;
flag |= CAPACITY_FORMATTED_PREEDIT;
flag |= CAPACITY_CLIENT_UNFOCUS_COMMIT;
m_useSurroundingText = get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= CAPACITY_SURROUNDING_TEXT;
/*
* event loop will cause some problem, so we tries to use async way.
*/
m_syncMode = get_boolean_env("FCITX_QT_USE_SYNC", false);
addCapacity(data, flag, true);
} while(0);
delete watcher;
}
void QFcitxPlatformInputContext::updateCapacity(FcitxQtICData* data)
{
if (!data->proxy || !data->proxy->isValid())
return;
QDBusPendingReply< void > result = data->proxy->SetCapacity((uint) data->capacity);
}
void QFcitxPlatformInputContext::commitString(const QString& str)
{
m_cursorPos = 0;
m_preeditList.clear();
m_commitPreedit.clear();
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodEvent event;
event.setCommitString(str);
QCoreApplication::sendEvent(input, &event);
}
void QFcitxPlatformInputContext::updateFormattedPreedit(const FcitxQtFormattedPreeditList& preeditList, int cursorPos)
{
QObject *input = qApp->focusObject();
if (!input)
return;
if (cursorPos == m_cursorPos && preeditList == m_preeditList)
return;
m_preeditList = preeditList;
m_cursorPos = cursorPos;
QString str, commitStr;
int pos = 0;
QList<QInputMethodEvent::Attribute> attrList;
Q_FOREACH(const FcitxQtFormattedPreedit& preedit, preeditList)
{
str += preedit.string();
if (!(preedit.format() & MSG_DONOT_COMMIT_WHEN_UNFOCUS))
commitStr += preedit.string();
QTextCharFormat format;
if ((preedit.format() & MSG_NOUNDERLINE) == 0) {
format.setUnderlineStyle(QTextCharFormat::DashUnderline);
}
if (preedit.format() & MSG_HIGHLIGHT) {
QBrush brush;
QPalette palette;
palette = QGuiApplication::palette();
format.setBackground(QBrush(QColor(palette.color(QPalette::Active, QPalette::Highlight))));
format.setForeground(QBrush(QColor(palette.color(QPalette::Active, QPalette::HighlightedText))));
}
attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, pos, preedit.string().length(), format));
pos += preedit.string().length();
}
QByteArray array = str.toUtf8();
array.truncate(cursorPos);
cursorPos = QString::fromUtf8(array).length();
attrList.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, 1, 0));
m_preedit = str;
m_commitPreedit = commitStr;
QInputMethodEvent event(str, attrList);
QCoreApplication::sendEvent(input, &event);
update(Qt::ImCursorRectangle);
}
void QFcitxPlatformInputContext::deleteSurroundingText(int offset, uint nchar)
{
QObject *input = qApp->focusObject();
if (!input)
return;
QInputMethodEvent event;
event.setCommitString("", offset, nchar);
QCoreApplication::sendEvent(input, &event);
}
void QFcitxPlatformInputContext::forwardKey(uint keyval, uint state, int type)
{
QObject *input = qApp->focusObject();
if (input != NULL) {
key_filtered = true;
QKeyEvent *keyevent = createKeyEvent(keyval, state, type);
QCoreApplication::sendEvent(input, keyevent);
delete keyevent;
key_filtered = false;
}
}
void QFcitxPlatformInputContext::createICData(QWindow* w)
{
FcitxQtICData* data = m_icMap.value(w->winId());
if (!data) {
data = new FcitxQtICData;
m_icMap[w->winId()] = data;
m_windowToWidMap[w] = w->winId();
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*)));
}
createInputContext(w->winId());
}
QKeyEvent* QFcitxPlatformInputContext::createKeyEvent(uint keyval, uint state, int type)
{
Qt::KeyboardModifiers qstate = Qt::NoModifier;
int count = 1;
if (state & FcitxKeyState_Alt) {
qstate |= Qt::AltModifier;
count ++;
}
if (state & FcitxKeyState_Shift) {
qstate |= Qt::ShiftModifier;
count ++;
}
if (state & FcitxKeyState_Ctrl) {
qstate |= Qt::ControlModifier;
count ++;
}
int key;
symToKeyQt(keyval, key);
QKeyEvent* keyevent = new QKeyEvent(
(type == FCITX_PRESS_KEY) ? (QEvent::KeyPress) : (QEvent::KeyRelease),
key,
qstate,
QString(),
false,
count
);
return keyevent;
}
bool QFcitxPlatformInputContext::filterEvent(const QEvent* event)
{
do {
if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) {
break;
}
const QKeyEvent* keyEvent = static_cast<const QKeyEvent*>(event);
quint32 keyval = keyEvent->nativeVirtualKey();
quint32 keycode = keyEvent->nativeScanCode();
quint32 state = keyEvent->nativeModifiers();
bool press = keyEvent->type() == QEvent::KeyPress;
if (key_filtered) {
break;
}
if (!inputMethodAccepted())
break;
QObject *input = qApp->focusObject();
if (!input) {
break;
}
FcitxQtInputContextProxy* proxy = validICByWindow(qApp->focusWindow());
if (!proxy) {
if (filterEventFallback(keyval, keycode, state, press)) {
return true;
} else {
break;
}
}
proxy->FocusIn();
QDBusPendingReply< int > reply = proxy->ProcessKeyEvent(keyval,
keycode,
state,
(press) ? FCITX_PRESS_KEY : FCITX_RELEASE_KEY,
QDateTime::currentDateTime().toTime_t());
if (Q_UNLIKELY(m_syncMode)) {
reply.waitForFinished();
if (!m_connection->isConnected() || !reply.isFinished() || reply.isError() || reply.value() <= 0) {
if (filterEventFallback(keyval, keycode, state, press)) {
return true;
} else {
break;
}
} else {
update(Qt::ImCursorRectangle);
return true;
}
}
else {
ProcessKeyWatcher* watcher = new ProcessKeyWatcher(*keyEvent, qApp->focusWindow(), reply, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this, SLOT(processKeyEventFinished(QDBusPendingCallWatcher*)));
return true;
}
} while(0);
return QPlatformInputContext::filterEvent(event);
}
void QFcitxPlatformInputContext::processKeyEventFinished(QDBusPendingCallWatcher* w)
{
ProcessKeyWatcher* watcher = static_cast<ProcessKeyWatcher*>(w);
QDBusPendingReply< int > result(*watcher);
bool filtered = false;
QWindow* window = watcher->window();
// if window is already destroyed, we can only throw this event away.
if (!window) {
return;
}
const QKeyEvent& keyEvent = watcher->event();
// use same variable name as in QXcbKeyboard::handleKeyEvent
QEvent::Type type = keyEvent.type();
int qtcode = keyEvent.key();
Qt::KeyboardModifiers modifiers = keyEvent.modifiers();
quint32 code = keyEvent.nativeScanCode();
quint32 sym = keyEvent.nativeVirtualKey();
quint32 state = keyEvent.nativeModifiers();
QString string = keyEvent.text();
bool isAutoRepeat = keyEvent.isAutoRepeat();
ulong time = keyEvent.timestamp();
if (result.isError() || result.value() <= 0) {
filtered = filterEventFallback(sym, code, state, type == QEvent::KeyPress);
} else {
filtered = true;
}
if (!result.isError()) {
update(Qt::ImCursorRectangle);
}
if (!filtered) {
// copied from QXcbKeyboard::handleKeyEvent()
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos();
const QPoint pos = window->mapFromGlobal(globalPos); QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers);
}
QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
code, sym, state, string, isAutoRepeat);
}
delete watcher;
}
bool QFcitxPlatformInputContext::filterEventFallback(uint keyval, uint keycode, uint state, bool press)
{
Q_UNUSED(keycode);
if (processCompose(keyval, state, (press) ? FCITX_PRESS_KEY : FCITX_RELEASE_KEY)) {
return true;
}
return false;
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validIC()
{
if (m_icMap.isEmpty()) {
return 0;
}
QWindow* window = qApp->focusWindow();
return validICByWindow(window);
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validICByWId(WId wid)
{
if (m_icMap.isEmpty()) {
return 0;
}
FcitxQtICData* icData = m_icMap.value(wid);
if (!icData)
return 0;
if (icData->proxy.isNull()) {
return 0;
} else if (icData->proxy->isValid()) {
return icData->proxy.data();
}
return 0;
}
FcitxQtInputContextProxy* QFcitxPlatformInputContext::validICByWindow(QWindow* w)
{
if (!w) {
return 0;
}
if (m_icMap.isEmpty()) {
return 0;
}
return validICByWId(w->winId());
}
bool QFcitxPlatformInputContext::processCompose(uint keyval, uint state, FcitxKeyEventType event)
{
Q_UNUSED(state);
if (!m_xkbComposeTable || event == FCITX_RELEASE_KEY)
return false;
struct xkb_compose_state* xkbComposeState = m_xkbComposeState.data();
enum xkb_compose_feed_result result = xkb_compose_state_feed(xkbComposeState, keyval);
if (result == XKB_COMPOSE_FEED_IGNORED) {
return false;
}
enum xkb_compose_status status = xkb_compose_state_get_status(xkbComposeState);
if (status == XKB_COMPOSE_NOTHING) {
return 0;
} else if (status == XKB_COMPOSE_COMPOSED) {
char buffer[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0'};
int length = xkb_compose_state_get_utf8(xkbComposeState, buffer, sizeof(buffer));
xkb_compose_state_reset(xkbComposeState);
if (length != 0) {
commitString(QString::fromUtf8(buffer));
}
} else if (status == XKB_COMPOSE_CANCELLED) {
xkb_compose_state_reset(xkbComposeState);
}
return true;
}
// kate: indent-mode cstyle; space-indent on; indent-width 0;

View File

@@ -0,0 +1,269 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef QFCITXPLATFORMINPUTCONTEXT_H
#define QFCITXPLATFORMINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
#include <QWindow>
#include <QKeyEvent>
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QPointer>
#include <QFileSystemWatcher>
#include <QRect>
#include <xkbcommon/xkbcommon-compose.h>
#include "fcitxqtformattedpreedit.h"
#include "fcitxqtinputcontextproxy.h"
#define MAX_COMPOSE_LEN 7
class FcitxQtConnection;
class QFileSystemWatcher;
enum FcitxKeyEventType {
FCITX_PRESS_KEY,
FCITX_RELEASE_KEY
};
enum FcitxCapacityFlags {
CAPACITY_NONE = 0,
CAPACITY_CLIENT_SIDE_UI = (1 << 0),
CAPACITY_PREEDIT = (1 << 1),
CAPACITY_CLIENT_SIDE_CONTROL_STATE = (1 << 2),
CAPACITY_PASSWORD = (1 << 3),
CAPACITY_FORMATTED_PREEDIT = (1 << 4),
CAPACITY_CLIENT_UNFOCUS_COMMIT = (1 << 5),
CAPACITY_SURROUNDING_TEXT = (1 << 6),
CAPACITY_EMAIL = (1 << 7),
CAPACITY_DIGIT = (1 << 8),
CAPACITY_UPPERCASE = (1 << 9),
CAPACITY_LOWERCASE = (1 << 10),
CAPACITY_NOAUTOUPPERCASE = (1 << 11),
CAPACITY_URL = (1 << 12),
CAPACITY_DIALABLE = (1 << 13),
CAPACITY_NUMBER = (1 << 14),
CAPACITY_NO_ON_SCREEN_KEYBOARD = (1 << 15),
CAPACITY_SPELLCHECK = (1 << 16),
CAPACITY_NO_SPELLCHECK = (1 << 17),
CAPACITY_WORD_COMPLETION = (1 << 18),
CAPACITY_UPPERCASE_WORDS = (1 << 19),
CAPACITY_UPPERCASE_SENTENCES = (1 << 20),
CAPACITY_ALPHA = (1 << 21),
CAPACITY_NAME = (1 << 22)
} ;
/** message type and flags */
enum FcitxMessageType {
MSG_TYPE_FIRST = 0,
MSG_TYPE_LAST = 6,
MSG_TIPS = 0, /**< Hint Text */
MSG_INPUT = 1, /**< User Input */
MSG_INDEX = 2, /**< Index Number */
MSG_FIRSTCAND = 3, /**< First candidate */
MSG_USERPHR = 4, /**< User Phrase */
MSG_CODE = 5, /**< Typed character */
MSG_OTHER = 6, /**< Other Text */
MSG_NOUNDERLINE = (1 << 3), /**< backward compatible, no underline is a flag */
MSG_HIGHLIGHT = (1 << 4), /**< highlight the preedit */
MSG_DONOT_COMMIT_WHEN_UNFOCUS = (1 << 5), /**< backward compatible */
MSG_REGULAR_MASK = 0x7 /**< regular color type mask */
};
enum FcitxKeyState {
FcitxKeyState_None = 0,
FcitxKeyState_Shift = 1 << 0,
FcitxKeyState_CapsLock = 1 << 1,
FcitxKeyState_Ctrl = 1 << 2,
FcitxKeyState_Alt = 1 << 3,
FcitxKeyState_Alt_Shift = FcitxKeyState_Alt | FcitxKeyState_Shift,
FcitxKeyState_Ctrl_Shift = FcitxKeyState_Ctrl | FcitxKeyState_Shift,
FcitxKeyState_Ctrl_Alt = FcitxKeyState_Ctrl | FcitxKeyState_Alt,
FcitxKeyState_Ctrl_Alt_Shift = FcitxKeyState_Ctrl | FcitxKeyState_Alt | FcitxKeyState_Shift,
FcitxKeyState_NumLock = 1 << 4,
FcitxKeyState_Super = 1 << 6,
FcitxKeyState_ScrollLock = 1 << 7,
FcitxKeyState_MousePressed = 1 << 8,
FcitxKeyState_HandledMask = 1 << 24,
FcitxKeyState_IgnoredMask = 1 << 25,
FcitxKeyState_Super2 = 1 << 26,
FcitxKeyState_Hyper = 1 << 27,
FcitxKeyState_Meta = 1 << 28,
FcitxKeyState_UsedMask = 0x5c001fff
};
struct FcitxQtICData {
FcitxQtICData() : capacity(0), proxy(0), surroundingAnchor(-1), surroundingCursor(-1) {}
~FcitxQtICData() {
if (proxy && proxy->isValid()) {
proxy->DestroyIC();
delete proxy;
}
}
QFlags<FcitxCapacityFlags> capacity;
QPointer<FcitxQtInputContextProxy> proxy;
QRect rect;
QString surroundingText;
int surroundingAnchor;
int surroundingCursor;
};
class ProcessKeyWatcher : public QDBusPendingCallWatcher
{
Q_OBJECT
public:
ProcessKeyWatcher(const QKeyEvent& event, QWindow* window, const QDBusPendingCall &call, QObject *parent = 0) :
QDBusPendingCallWatcher(call, parent)
,m_event(event.type(), event.key(), event.modifiers(),
event.nativeScanCode(), event.nativeVirtualKey(), event.nativeModifiers(),
event.text(), event.isAutoRepeat(), event.count())
,m_window(window)
{
}
virtual ~ProcessKeyWatcher() {
}
const QKeyEvent& event() {
return m_event;
}
QWindow* window() {
return m_window.data();
}
private:
QKeyEvent m_event;
QPointer<QWindow> m_window;
};
struct XkbContextDeleter
{
static inline void cleanup(struct xkb_context* pointer)
{
if (pointer) xkb_context_unref(pointer);
}
};
struct XkbComposeTableDeleter
{
static inline void cleanup(struct xkb_compose_table* pointer)
{
if (pointer) xkb_compose_table_unref(pointer);
}
};
struct XkbComposeStateDeleter
{
static inline void cleanup(struct xkb_compose_state* pointer)
{
if (pointer) xkb_compose_state_unref(pointer);
}
};
class FcitxQtInputMethodProxy;
class QFcitxPlatformInputContext : public QPlatformInputContext
{
Q_OBJECT
public:
QFcitxPlatformInputContext();
virtual ~QFcitxPlatformInputContext();
virtual bool filterEvent(const QEvent* event);
virtual bool isValid() const;
virtual void invokeAction(QInputMethod::Action , int cursorPosition);
virtual void reset();
virtual void commit();
virtual void update(Qt::InputMethodQueries quries );
virtual void setFocusObject(QObject* object);
public Q_SLOTS:
void cursorRectChanged();
void commitString(const QString& str);
void updateFormattedPreedit(const FcitxQtFormattedPreeditList& preeditList, int cursorPos);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, int type);
void createInputContextFinished(QDBusPendingCallWatcher* watcher);
void connected();
void cleanUp();
void windowDestroyed(QObject* object);
private:
void createInputContext(WId w);
bool processCompose(uint keyval, uint state, FcitxKeyEventType event);
bool checkAlgorithmically();
bool checkCompactTable(const struct _FcitxComposeTableCompact *table);
QKeyEvent* createKeyEvent(uint keyval, uint state, int type);
void addCapacity(FcitxQtICData* data, QFlags<FcitxCapacityFlags> capacity, bool forceUpdate = false)
{
QFlags< FcitxCapacityFlags > newcaps = data->capacity | capacity;
if (data->capacity != newcaps || forceUpdate) {
data->capacity = newcaps;
updateCapacity(data);
}
}
void removeCapacity(FcitxQtICData* data, QFlags<FcitxCapacityFlags> capacity, bool forceUpdate = false)
{
QFlags< FcitxCapacityFlags > newcaps = data->capacity & (~capacity);
if (data->capacity != newcaps || forceUpdate) {
data->capacity = newcaps;
updateCapacity(data);
}
}
void updateCapacity(FcitxQtICData* data);
void commitPreedit();
void createICData(QWindow* w);
FcitxQtInputContextProxy* validIC();
FcitxQtInputContextProxy* validICByWindow(QWindow* window);
FcitxQtInputContextProxy* validICByWId(WId wid);
bool filterEventFallback(uint keyval, uint keycode, uint state, bool press);
FcitxQtInputMethodProxy* m_improxy;
uint m_compose_buffer[MAX_COMPOSE_LEN + 1];
int m_n_compose;
QString m_preedit;
QString m_commitPreedit;
FcitxQtFormattedPreeditList m_preeditList;
int m_cursorPos;
bool m_useSurroundingText;
bool m_syncMode;
FcitxQtConnection* m_connection;
QString m_lastSurroundingText;
int m_lastSurroundingAnchor;
int m_lastSurroundingCursor;
QHash<WId, FcitxQtICData*> m_icMap;
QHash<QObject*, WId> m_windowToWidMap;
WId m_lastWId;
bool m_destroy;
QScopedPointer<struct xkb_context, XkbContextDeleter> m_xkbContext;
QScopedPointer<struct xkb_compose_table, XkbComposeTableDeleter> m_xkbComposeTable;
QScopedPointer<struct xkb_compose_state, XkbComposeStateDeleter> m_xkbComposeState;
private slots:
void processKeyEventFinished(QDBusPendingCallWatcher*);
};
#endif // QFCITXPLATFORMINPUTCONTEXT_H

View File

@@ -0,0 +1,177 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "utils.h"
/** check utf8 character */
#define ISUTF8_CB(c) (((c)&0xc0) == 0x80)
#define CONT(i) ISUTF8_CB(in[i])
#define VAL(i, s) ((in[i]&0x3f) << s)
#define UTF8_LENGTH(Char) \
((Char) < 0x80 ? 1 : \
((Char) < 0x800 ? 2 : \
((Char) < 0x10000 ? 3 : \
((Char) < 0x200000 ? 4 : \
((Char) < 0x4000000 ? 5 : 6)))))
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFE) != 0xFFFE)
int
_utf8_get_char_extended(const char *s,
int max_len)
{
const unsigned char*p = (const unsigned char*)s;
int i, len;
unsigned int wc = (unsigned char) * p;
if (wc < 0x80) {
return wc;
} else if (wc < 0xc0) {
return (unsigned int) - 1;
} else if (wc < 0xe0) {
len = 2;
wc &= 0x1f;
} else if (wc < 0xf0) {
len = 3;
wc &= 0x0f;
} else if (wc < 0xf8) {
len = 4;
wc &= 0x07;
} else if (wc < 0xfc) {
len = 5;
wc &= 0x03;
} else if (wc < 0xfe) {
len = 6;
wc &= 0x01;
} else {
return (unsigned int) - 1;
}
if (max_len >= 0 && len > max_len) {
for (i = 1; i < max_len; i++) {
if ((((unsigned char *)p)[i] & 0xc0) != 0x80)
return (unsigned int) - 1;
}
return (unsigned int) - 2;
}
for (i = 1; i < len; ++i) {
unsigned int ch = ((unsigned char *)p)[i];
if ((ch & 0xc0) != 0x80) {
if (ch)
return (unsigned int) - 1;
else
return (unsigned int) - 2;
}
wc <<= 6;
wc |= (ch & 0x3f);
}
if (UTF8_LENGTH(wc) != len)
return (unsigned int) - 1;
return wc;
}
int _utf8_get_char_validated(const char *p,
int max_len)
{
int result;
if (max_len == 0)
return -2;
result = _utf8_get_char_extended(p, max_len);
if (result & 0x80000000)
return result;
else if (!UNICODE_VALID(result))
return -1;
else
return result;
}
char *
_utf8_get_char(const char *i, uint32_t *chr)
{
const unsigned char* in = (const unsigned char *)i;
if (!(in[0] & 0x80)) {
*(chr) = *(in);
return (char *)in + 1;
}
/* 2-byte, 0x80-0x7ff */
if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
*chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
return (char *)in + 2;
}
/* 3-byte, 0x800-0xffff */
if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
*chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
return (char *)in + 3;
}
/* 4-byte, 0x10000-0x1FFFFF */
if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
*chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
return (char *)in + 4;
}
/* 5-byte, 0x200000-0x3FFFFFF */
if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
*chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
return (char *)in + 5;
}
/* 6-byte, 0x400000-0x7FFFFFF */
if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
*chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
return (char *)in + 6;
}
*chr = *in;
return (char *)in + 1;
}
int _utf8_check_string(const char *s)
{
while (*s) {
uint32_t chr;
if (_utf8_get_char_validated(s, 6) < 0)
return 0;
s = _utf8_get_char(s, &chr);
}
return 1;
}

View File

@@ -0,0 +1,35 @@
/***************************************************************************
* Copyright (C) 2012~2013 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef UTILS_H
#define UTILS_H
#include <stdint.h>
int
_utf8_get_char_extended(const char *s,
int max_len);
int _utf8_get_char_validated(const char *p,
int max_len);
char *
_utf8_get_char(const char *i, uint32_t *chr);
int _utf8_check_string(const char *s);
#endif // UTILS_H

View File

@@ -0,0 +1,98 @@
/*
* Copyright © 2012 Daniel Stone
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#ifndef _XKBCOMMON_COMPAT_H
#define _XKBCOMMON_COMPAT_H
/**
* Renamed keymap API.
*/
#define xkb_group_index_t xkb_layout_index_t
#define xkb_group_mask_t xkb_layout_mask_t
#define xkb_map_compile_flags xkb_keymap_compile_flags
#define XKB_GROUP_INVALID XKB_LAYOUT_INVALID
#define XKB_STATE_DEPRESSED \
(XKB_STATE_MODS_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED)
#define XKB_STATE_LATCHED \
(XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_LATCHED)
#define XKB_STATE_LOCKED \
(XKB_STATE_MODS_LOCKED | XKB_STATE_LAYOUT_LOCKED)
#define XKB_STATE_EFFECTIVE \
(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED | \
XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LAYOUT_EFFECTIVE)
#define xkb_map_new_from_names(context, names, flags) \
xkb_keymap_new_from_names(context, names, flags)
#define xkb_map_new_from_file(context, file, format, flags) \
xkb_keymap_new_from_file(context, file, format, flags)
#define xkb_map_new_from_string(context, string, format, flags) \
xkb_keymap_new_from_string(context, string, format, flags)
#define xkb_map_get_as_string(keymap) \
xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1)
#define xkb_map_ref(keymap) xkb_keymap_ref(keymap)
#define xkb_map_unref(keymap) xkb_keymap_unref(keymap)
#define xkb_map_num_mods(keymap) xkb_keymap_num_mods(keymap)
#define xkb_map_mod_get_name(keymap, idx) xkb_keymap_mod_get_name(keymap, idx)
#define xkb_map_mod_get_index(keymap, str) xkb_keymap_mod_get_index(keymap, str)
#define xkb_key_mod_index_is_consumed(state, key, mod) \
xkb_state_mod_index_is_consumed(state, key, mod)
#define xkb_key_mod_mask_remove_consumed(state, key, modmask) \
xkb_state_mod_mask_remove_consumed(state, key, modmask)
#define xkb_map_num_groups(keymap) xkb_keymap_num_layouts(keymap)
#define xkb_key_num_groups(keymap, key) \
xkb_keymap_num_layouts_for_key(keymap, key)
#define xkb_map_group_get_name(keymap, idx) \
xkb_keymap_layout_get_name(keymap, idx)
#define xkb_map_group_get_index(keymap, str) \
xkb_keymap_layout_get_index(keymap, str)
#define xkb_map_num_leds(keymap) xkb_keymap_num_leds(keymap)
#define xkb_map_led_get_name(keymap, idx) xkb_keymap_led_get_name(keymap, idx)
#define xkb_map_led_get_index(keymap, str) \
xkb_keymap_led_get_index(keymap, str)
#define xkb_key_repeats(keymap, key) xkb_keymap_key_repeats(keymap, key)
#define xkb_key_get_syms(state, key, syms_out) \
xkb_state_key_get_syms(state, key, syms_out)
#define xkb_state_group_name_is_active(state, name, type) \
xkb_state_layout_name_is_active(state, name, type)
#define xkb_state_group_index_is_active(state, idx, type) \
xkb_state_layout_index_is_active(state, idx, type)
#define xkb_state_serialize_group(state, component) \
xkb_state_serialize_layout(state, component)
#define xkb_state_get_map(state) xkb_state_get_keymap(state)
/* Not needed anymore, since there's NO_FLAGS. */
#define XKB_MAP_COMPILE_PLACEHOLDER XKB_KEYMAP_COMPILE_NO_FLAGS
#define XKB_MAP_COMPILE_NO_FLAGS XKB_KEYMAP_COMPILE_NO_FLAGS
#endif

View File

@@ -0,0 +1,488 @@
/*
* Copyright © 2013 Ran Benita
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _XKBCOMMON_COMPOSE_H
#define _XKBCOMMON_COMPOSE_H
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* libxkbcommon Compose API - support for Compose and dead-keys.
*/
/**
* @defgroup compose Compose and dead-keys support
* Support for Compose and dead-keys.
* @since 0.5.0
*
* @{
*/
/**
* @page compose-overview Overview
* @parblock
*
* Compose and dead-keys are a common feature of many keyboard input
* systems. They extend the range of the keysysm that can be produced
* directly from a keyboard by using a sequence of key strokes, instead
* of just one.
*
* Here are some example sequences, in the libX11 Compose file format:
*
* <dead_acute> <a> : "á" aacute # LATIN SMALL LETTER A WITH ACUTE
* <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
*
* When the user presses a key which produces the `<dead_acute>` keysym,
* nothing initially happens (thus the key is dubbed a "dead-key"). But
* when the user enters `<a>`, "á" is "composed", in place of "a". If
* instead the user had entered a keysym which does not follow
* `<dead_acute>` in any compose sequence, the sequence is said to be
* "cancelled".
*
* Compose files define many such sequences. For a description of the
* common file format for Compose files, see the Compose(5) man page.
*
* A successfuly-composed sequence has two results: a keysym and a UTF-8
* string. At least one of the two is defined for each sequence. If only
* a keysym is given, the keysym's string representation is used for the
* result string (using xkb_keysym_to_utf8()).
*
* This library provides low-level support for Compose file parsing and
* processing. Higher-level APIs (such as libX11's `Xutf8LookupString`(3))
* may be built upon it, or it can be used directly.
*
* @endparblock
*/
/**
* @page compose-conflicting Conflicting Sequences
* @parblock
*
* To avoid ambiguity, a sequence is not allowed to be a prefix of another.
* In such a case, the conflict is resolved thus:
*
* 1. A longer sequence overrides a shorter one.
* 2. An equal sequence overrides an existing one.
* 3. A shorter sequence does not override a longer one.
*
* Sequences of length 1 are allowed.
*
* @endparblock
*/
/**
* @page compose-cancellation Cancellation Behavior
* @parblock
*
* What should happen when a sequence is cancelled? For example, consider
* there are only the above sequences, and the input keysyms are
* `<dead_acute> <b>`. There are a few approaches:
*
* 1. Swallow the cancelling keysym; that is, no keysym is produced.
* This is the approach taken by libX11.
* 2. Let the cancelling keysym through; that is, `<b>` is produced.
* 3. Replay the entire sequence; that is, `<dead_acute> <b>` is produced.
* This is the approach taken by Microsoft Windows (approximately;
* instead of `<dead_acute>`, the underlying key is used. This is
* difficult to simulate with XKB keymaps).
*
* You can program whichever approach best fits users' expectations.
*
* @endparblock
*/
/**
* @struct xkb_compose_table
* Opaque Compose table object.
*
* The compose table holds the definitions of the Compose sequences, as
* gathered from Compose files. It is immutable.
*/
struct xkb_compose_table;
/**
* @struct xkb_compose_state
* Opaque Compose state object.
*
* The compose state maintains state for compose sequence matching, such
* as which possible sequences are being matched, and the position within
* these sequences. It acts as a simple state machine wherein keysyms are
* the input, and composed keysyms and strings are the output.
*
* The compose state is usually associated with a keyboard device.
*/
struct xkb_compose_state;
/** Flags affecting Compose file compilation. */
enum xkb_compose_compile_flags {
/** Do not apply any flags. */
XKB_COMPOSE_COMPILE_NO_FLAGS = 0
};
/** The recognized Compose file formats. */
enum xkb_compose_format {
/** The classic libX11 Compose text format, described in Compose(5). */
XKB_COMPOSE_FORMAT_TEXT_V1 = 1
};
/**
* @page compose-locale Compose Locale
* @parblock
*
* Compose files are locale dependent:
* - Compose files are written for a locale, and the locale is used when
* searching for the appropriate file to use.
* - Compose files may reference the locale internally, with directives
* such as \%L.
*
* As such, functions like xkb_compose_table_new_from_locale() require
* a `locale` parameter. This will usually be the current locale (see
* locale(7) for more details). You may also want to allow the user to
* explicitly configure it, so he can use the Compose file of a given
* locale, but not use that locale for other things.
*
* You may query the current locale as follows:
* @code
* const char *locale;
* locale = setlocale(LC_CTYPE, NULL);
* @endcode
*
* This will only give useful results if the program had previously set
* the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL`
* and a non-NULL argument.
*
* If you prefer not to use the locale system of the C runtime library,
* you may nevertheless obtain the user's locale directly using
* environment variables, as described in locale(7). For example,
* @code
* locale = getenv("LC_ALL");
* if (!locale)
* locale = getenv("LC_CTYPE");
* if (!locale)
* locale = getenv("LANG");
* if (!locale)
* locale = "C";
* @endcode
*
* Note that some locales supported by the C standard library may not
* have a Compose file assigned.
*
* @endparblock
*/
/**
* Create a compose table for a given locale.
*
* The locale is used for searching the file-system for an appropriate
* Compose file. The search order is described in Compose(5). It is
* affected by the following environment variables:
*
* 1. `XCOMPOSEFILE` - see Compose(5).
* 2. `HOME` - see Compose(5).
* 3. `XLOCALEDIR` - if set, used as the base directory for the system's
* X locale files, e.g. `/usr/share/X11/locale`, instead of the
* preconfigured directory.
*
* @param context
* The library context in which to create the compose table.
* @param locale
* The current locale. See @ref compose-locale.
* @param flags
* Optional flags for the compose table, or 0.
*
* @returns A compose table for the given locale, or NULL if the
* compilation failed or a Compose file was not found.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_locale(struct xkb_context *context,
const char *locale,
enum xkb_compose_compile_flags flags);
/**
* Create a new compose table from a Compose file.
*
* @param context
* The library context in which to create the compose table.
* @param file
* The Compose file to compile.
* @param locale
* The current locale. See @ref compose-locale.
* @param format
* The text format of the Compose file to compile.
* @param flags
* Optional flags for the compose table, or 0.
*
* @returns A compose table compiled from the given file, or NULL if
* the compilation failed.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_file(struct xkb_context *context,
FILE *file,
const char *locale,
enum xkb_compose_format format,
enum xkb_compose_compile_flags flags);
/**
* Create a new compose table from a memory buffer.
*
* This is just like xkb_compose_table_new_from_file(), but instead of
* a file, gets the table as one enormous string.
*
* @see xkb_compose_table_new_from_file()
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_new_from_buffer(struct xkb_context *context,
const char *buffer, size_t length,
const char *locale,
enum xkb_compose_format format,
enum xkb_compose_compile_flags flags);
/**
* Take a new reference on a compose table.
*
* @returns The passed in object.
*
* @memberof xkb_compose_table
*/
struct xkb_compose_table *
xkb_compose_table_ref(struct xkb_compose_table *table);
/**
* Release a reference on a compose table, and possibly free it.
*
* @param table The object. If it is NULL, this function does nothing.
*
* @memberof xkb_compose_table
*/
void
xkb_compose_table_unref(struct xkb_compose_table *table);
/** Flags for compose state creation. */
enum xkb_compose_state_flags {
/** Do not apply any flags. */
XKB_COMPOSE_STATE_NO_FLAGS = 0
};
/**
* Create a new compose state object.
*
* @param table
* The compose table the state will use.
* @param flags
* Optional flags for the compose state, or 0.
*
* @returns A new compose state, or NULL on failure.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_state *
xkb_compose_state_new(struct xkb_compose_table *table,
enum xkb_compose_state_flags flags);
/**
* Take a new reference on a compose state object.
*
* @returns The passed in object.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_state *
xkb_compose_state_ref(struct xkb_compose_state *state);
/**
* Release a reference on a compose state object, and possibly free it.
*
* @param state The object. If NULL, do nothing.
*
* @memberof xkb_compose_state
*/
void
xkb_compose_state_unref(struct xkb_compose_state *state);
/**
* Get the compose table which a compose state object is using.
*
* @returns The compose table which was passed to xkb_compose_state_new()
* when creating this state object.
*
* This function does not take a new reference on the compose table; you
* must explicitly reference it yourself if you plan to use it beyond the
* lifetime of the state.
*
* @memberof xkb_compose_state
*/
struct xkb_compose_table *
xkb_compose_state_get_compose_table(struct xkb_compose_state *state);
/** Status of the Compose sequence state machine. */
enum xkb_compose_status {
/** The initial state; no sequence has started yet. */
XKB_COMPOSE_NOTHING,
/** In the middle of a sequence. */
XKB_COMPOSE_COMPOSING,
/** A complete sequence has been matched. */
XKB_COMPOSE_COMPOSED,
/** The last sequence was cancelled due to an unmatched keysym. */
XKB_COMPOSE_CANCELLED
};
/** The effect of a keysym fed to xkb_compose_state_feed(). */
enum xkb_compose_feed_result {
/** The keysym had no effect - it did not affect the status. */
XKB_COMPOSE_FEED_IGNORED,
/** The keysym started, advanced or cancelled a sequence. */
XKB_COMPOSE_FEED_ACCEPTED
};
/**
* Feed one keysym to the Compose sequence state machine.
*
* This function can advance into a compose sequence, cancel a sequence,
* start a new sequence, or do nothing in particular. The resulting
* status may be observed with xkb_compose_state_get_status().
*
* Some keysyms, such as keysyms for modifier keys, are ignored - they
* have no effect on the status or otherwise.
*
* The following is a description of the possible status transitions, in
* the format CURRENT STATUS => NEXT STATUS, given a non-ignored input
* keysym `keysym`:
*
@verbatim
NOTHING or CANCELLED or COMPOSED =>
NOTHING if keysym does not start a sequence.
COMPOSING if keysym starts a sequence.
COMPOSED if keysym starts and terminates a single-keysym sequence.
COMPOSING =>
COMPOSING if keysym advances any of the currently possible
sequences but does not terminate any of them.
COMPOSED if keysym terminates one of the currently possible
sequences.
CANCELLED if keysym does not advance any of the currently
possible sequences.
@endverbatim
*
* The current Compose formats do not support multiple-keysyms.
* Therefore, if you are using a function such as xkb_state_key_get_syms()
* and it returns more than one keysym, consider feeding XKB_KEY_NoSymbol
* instead.
*
* @param state
* The compose state object.
* @param keysym
* A keysym, usually obtained after a key-press event, with a
* function such as xkb_state_key_get_one_sym().
*
* @returns Whether the keysym was ignored. This is useful, for example,
* if you want to keep a record of the sequence matched thus far.
*
* @memberof xkb_compose_state
*/
enum xkb_compose_feed_result
xkb_compose_state_feed(struct xkb_compose_state *state,
xkb_keysym_t keysym);
/**
* Reset the Compose sequence state machine.
*
* The status is set to XKB_COMPOSE_NOTHING, and the current sequence
* is discarded.
*
* @memberof xkb_compose_state
*/
void
xkb_compose_state_reset(struct xkb_compose_state *state);
/**
* Get the current status of the compose state machine.
*
* @see xkb_compose_status
* @memberof xkb_compose_state
**/
enum xkb_compose_status
xkb_compose_state_get_status(struct xkb_compose_state *state);
/**
* Get the result Unicode/UTF-8 string for a composed sequence.
*
* See @ref compose-overview for more details. This function is only
* useful when the status is XKB_COMPOSE_COMPOSED.
*
* @param[in] state
* The compose state.
* @param[out] buffer
* A buffer to write the string into.
* @param[in] size
* Size of the buffer.
*
* @warning If the buffer passed is too small, the string is truncated
* (though still NUL-terminated).
*
* @returns
* The number of bytes required for the string, excluding the NUL byte.
* If the sequence is not complete, or does not have a viable result
* string, returns 0, and sets `buffer` to the empty string (if possible).
* @returns
* You may check if truncation has occurred by comparing the return value
* with the size of `buffer`, similarly to the `snprintf`(3) function.
* You may safely pass NULL and 0 to `buffer` and `size` to find the
* required size (without the NUL-byte).
*
* @memberof xkb_compose_state
**/
int
xkb_compose_state_get_utf8(struct xkb_compose_state *state,
char *buffer, size_t size);
/**
* Get the result keysym for a composed sequence.
*
* See @ref compose-overview for more details. This function is only
* useful when the status is XKB_COMPOSE_COMPOSED.
*
* @returns The result keysym. If the sequence is not complete, or does
* not specify a result keysym, returns XKB_KEY_NoSymbol.
*
* @memberof xkb_compose_state
**/
xkb_keysym_t
xkb_compose_state_get_one_sym(struct xkb_compose_state *state);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBCOMMON_COMPOSE_H */

View File

@@ -0,0 +1,45 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#ifndef _XKBCOMMON_NAMES_H
#define _XKBCOMMON_NAMES_H
/**
* @file
* @brief Predefined names for common modifiers and LEDs.
*/
#define XKB_MOD_NAME_SHIFT "Shift"
#define XKB_MOD_NAME_CAPS "Lock"
#define XKB_MOD_NAME_CTRL "Control"
#define XKB_MOD_NAME_ALT "Mod1"
#define XKB_MOD_NAME_NUM "Mod2"
#define XKB_MOD_NAME_LOGO "Mod4"
#define XKB_LED_NAME_CAPS "Caps Lock"
#define XKB_LED_NAME_NUM "Num Lock"
#define XKB_LED_NAME_SCROLL "Scroll Lock"
#endif

View File

@@ -0,0 +1,244 @@
/*
* Copyright © 2013 Ran Benita
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _XKBCOMMON_X11_H
#define _XKBCOMMON_X11_H
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* libxkbcommon-x11 API - Additional X11 support for xkbcommon.
*/
/**
* @defgroup x11 X11 support
* Additional X11 support for xkbcommon.
* @since 0.4.0
*
* @{
*/
/**
* @page x11-overview Overview
* @parblock
*
* The xkbcommon-x11 module provides a means for creating an xkb_keymap
* corresponding to the currently active keymap on the X server. To do
* so, it queries the XKB X11 extension using the xcb-xkb library. It
* can be used as a replacement for Xlib's keyboard handling.
*
* Following is an example workflow using xkbcommon-x11. A complete
* example may be found in the test/interactive-x11.c file in the
* xkbcommon source repository. On startup:
*
* 1. Connect to the X server using xcb_connect().
* 2. Setup the XKB X11 extension. You can do this either by using the
* xcb_xkb_use_extension() request directly, or by using the
* xkb_x11_setup_xkb_extension() helper function.
*
* The XKB extension supports using separate keymaps and states for
* different keyboard devices. The devices are identified by an integer
* device ID and are managed by another X11 extension, XInput (or its
* successor, XInput2). The original X11 protocol only had one keyboard
* device, called the "core keyboard", which is still supported as a
* "virtual device".
*
* 3. We will use the core keyboard as an example. To get its device ID,
* use either the xcb_xkb_get_device_info() request directly, or the
* xkb_x11_get_core_keyboard_device_id() helper function.
* 4. Create an initial xkb_keymap for this device, using the
* xkb_x11_keymap_new_from_device() function.
* 5. Create an initial xkb_state for this device, using the
* xkb_x11_state_new_from_device() function.
*
* @note At this point, you may consider setting various XKB controls and
* XKB per-client flags. For example, enabling detectable autorepeat: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
*
* Next, you need to react to state changes (e.g. a modifier was pressed,
* the layout was changed) and to keymap changes (e.g. a tool like xkbcomp,
* setxkbmap or xmodmap was used):
*
* 6. Select to listen to at least the following XKB events:
* NewKeyboardNotify, MapNotify, StateNotify; using the
* xcb_xkb_select_events_aux() request.
* 7. When NewKeyboardNotify or MapNotify are received, recreate the
* xkb_keymap and xkb_state as described above.
* 8. When StateNotify is received, update the xkb_state accordingly
* using the xkb_state_update_mask() function.
*
* @note It is also possible to use the KeyPress/KeyRelease @p state
* field to find the effective modifier and layout state, instead of
* using XkbStateNotify: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State
* \n However, XkbStateNotify is more accurate.
*
* @note There is no need to call xkb_state_update_key(); the state is
* already synchronized.
*
* Finally, when a key event is received, you can use ordinary xkbcommon
* functions, like xkb_state_key_get_one_sym() and xkb_state_key_get_utf8(),
* as you normally would.
*
* @endparblock
*/
/**
* The minimal compatible major version of the XKB X11 extension which
* this library can use.
*/
#define XKB_X11_MIN_MAJOR_XKB_VERSION 1
/**
* The minimal compatible minor version of the XKB X11 extension which
* this library can use (for the minimal major version).
*/
#define XKB_X11_MIN_MINOR_XKB_VERSION 0
/** Flags for the xkb_x11_setup_xkb_extension() function. */
enum xkb_x11_setup_xkb_extension_flags {
/** Do not apply any flags. */
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0
};
/**
* Setup the XKB X11 extension for this X client.
*
* The xkbcommon-x11 library uses various XKB requests. Before doing so,
* an X client must notify the server that it will be using the extension.
* This function (or an XCB equivalent) must be called before any other
* function in this library is used.
*
* Some X servers may not support or disable the XKB extension. If you
* want to support such servers, you need to use a different fallback.
*
* You may call this function several times; it is idempotent.
*
* @param connection
* An XCB connection to the X server.
* @param major_xkb_version
* See @p minor_xkb_version.
* @param minor_xkb_version
* The XKB extension version to request. To operate correctly, you
* must have (major_xkb_version, minor_xkb_version) >=
* (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION),
* though this is not enforced.
* @param flags
* Optional flags, or 0.
* @param[out] major_xkb_version_out
* See @p minor_xkb_version_out.
* @param[out] minor_xkb_version_out
* Backfilled with the compatible XKB extension version numbers picked
* by the server. Can be NULL.
* @param[out] base_event_out
* Backfilled with the XKB base (also known as first) event code, needed
* to distinguish XKB events. Can be NULL.
* @param[out] base_error_out
* Backfilled with the XKB base (also known as first) error code, needed
* to distinguish XKB errors. Can be NULL.
*
* @returns 1 on success, or 0 on failure.
*/
int
xkb_x11_setup_xkb_extension(xcb_connection_t *connection,
uint16_t major_xkb_version,
uint16_t minor_xkb_version,
enum xkb_x11_setup_xkb_extension_flags flags,
uint16_t *major_xkb_version_out,
uint16_t *minor_xkb_version_out,
uint8_t *base_event_out,
uint8_t *base_error_out);
/**
* Get the keyboard device ID of the core X11 keyboard.
*
* @param connection An XCB connection to the X server.
*
* @returns A device ID which may be used with other xkb_x11_* functions,
* or -1 on failure.
*/
int32_t
xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection);
/**
* Create a keymap from an X11 keyboard device.
*
* This function queries the X server with various requests, fetches the
* details of the active keymap on a keyboard device, and creates an
* xkb_keymap from these details.
*
* @param context
* The context in which to create the keymap.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
* @param flags
* Optional flags for the keymap, or 0.
*
* @returns A keymap retrieved from the X server, or NULL on failure.
*
* @memberof xkb_keymap
*/
struct xkb_keymap *
xkb_x11_keymap_new_from_device(struct xkb_context *context,
xcb_connection_t *connection,
int32_t device_id,
enum xkb_keymap_compile_flags flags);
/**
* Create a new keyboard state object from an X11 keyboard device.
*
* This function is the same as xkb_state_new(), only pre-initialized
* with the state of the device at the time this function is called.
*
* @param keymap
* The keymap for which to create the state.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
*
* @returns A new keyboard state object, or NULL on failure.
*
* @memberof xkb_state
*/
struct xkb_state *
xkb_x11_state_new_from_device(struct xkb_keymap *keymap,
xcb_connection_t *connection,
int32_t device_id);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBCOMMON_X11_H */

Some files were not shown because too many files have changed in this diff Show More