diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index c4952508eb..35ed14b870 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -436,7 +436,7 @@ void MainWindow::init() { setWindowIcon(wndIcon); Application::instance()->installEventFilter(this); - connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(stateChanged(Qt::WindowState))); + connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState))); connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(checkHistoryActivation()), Qt::QueuedConnection); QPalette p(palette()); diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.cpp b/Telegram/SourceFiles/platform/linux/linux_libs.cpp new file mode 100644 index 0000000000..2beea27ab8 --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_libs.cpp @@ -0,0 +1,184 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "platform/linux/linux_libs.h" + +namespace Platform { +namespace Libs { +namespace { + +bool loadLibrary(QLibrary &lib, const char *name, int version) { + DEBUG_LOG(("Loading '%1' with version %2...").arg(QLatin1String(name)).arg(version)); + lib.setFileNameAndVersion(QLatin1String(name), version); + if (lib.load()) { + DEBUG_LOG(("Loaded '%1' with version %2!").arg(QLatin1String(name)).arg(version)); + return true; + } + lib.setFileNameAndVersion(QLatin1String(name), QString()); + if (lib.load()) { + DEBUG_LOG(("Loaded '%1' without version!").arg(QLatin1String(name))); + return true; + } + LOG(("Could not load '%1' with version %2 :(").arg(QLatin1String(name)).arg(version)); + return false; +} + +bool setupGtkBase(QLibrary &lib_gtk) { + if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; + if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; + if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; + + if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; + if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; + if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; + if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; + if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; + if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; + if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; + if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; + + if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; + if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; + + if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; + if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; + + DEBUG_LOG(("Library gtk functions loaded!")); + if (!gtk_init_check(0, 0)) { + gtk_init_check = nullptr; + DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); + return false; + } + + DEBUG_LOG(("Checked gtk with gtk_init_check!")); + return true; +} + +bool setupAppIndicator(QLibrary &lib_indicator) { + if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; + if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; + if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; + if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; + + DEBUG_LOG(("Library appindicator functions loaded!")); + return true; +} + +} // namespace + +f_gtk_init_check gtk_init_check = nullptr; +f_gtk_menu_new gtk_menu_new = nullptr; +f_gtk_menu_get_type gtk_menu_get_type = nullptr; +f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label = nullptr; +f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr; +f_gtk_menu_shell_append gtk_menu_shell_append = nullptr; +f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr; +f_gtk_widget_show gtk_widget_show = nullptr; +f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr; +f_gtk_widget_get_visible gtk_widget_get_visible = nullptr; +f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr; +f_g_type_check_instance_cast g_type_check_instance_cast = nullptr; +f_g_signal_connect_data g_signal_connect_data = nullptr; +f_app_indicator_new app_indicator_new = nullptr; +f_app_indicator_set_status app_indicator_set_status = nullptr; +f_app_indicator_set_menu app_indicator_set_menu = nullptr; +f_app_indicator_set_icon_full app_indicator_set_icon_full = nullptr; +f_gdk_init_check gdk_init_check = nullptr; +f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr; +f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf = nullptr; +f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf = nullptr; +f_gtk_status_icon_set_title gtk_status_icon_set_title = nullptr; +f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text = nullptr; +f_gtk_status_icon_set_visible gtk_status_icon_set_visible = nullptr; +f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded = nullptr; +f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry = nullptr; +f_gtk_status_icon_position_menu gtk_status_icon_position_menu = nullptr; +f_gtk_menu_popup gtk_menu_popup = nullptr; +f_gtk_get_current_event_time gtk_get_current_event_time = nullptr; +f_g_object_ref_sink g_object_ref_sink = nullptr; +f_g_object_unref g_object_unref = nullptr; +f_g_idle_add g_idle_add = nullptr; +f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr; +f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr; +f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr; + +void start() { + DEBUG_LOG(("Loading libraries")); + + bool gtkLoaded = false; + bool indicatorLoaded = false; + QLibrary lib_gtk, lib_indicator; + if (loadLibrary(lib_indicator, "appindicator3", 1)) { + if (loadLibrary(lib_gtk, "gtk-3", 0)) { + gtkLoaded = setupGtkBase(lib_gtk); + indicatorLoaded = setupAppIndicator(lib_indicator); + } + } + if (!gtkLoaded || !indicatorLoaded) { + if (loadLibrary(lib_indicator, "appindicator", 1)) { + if (loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { + gtkLoaded = indicatorLoaded = false; + gtkLoaded = setupGtkBase(lib_gtk); + indicatorLoaded = setupAppIndicator(lib_indicator); + } + } + } + + // If no appindicator, try at least load gtk. + if (!gtkLoaded && !indicatorLoaded) { + if (loadLibrary(lib_gtk, "gtk-3", 0)) { + gtkLoaded = setupGtkBase(lib_gtk); + } + if (!gtkLoaded && loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { + gtkLoaded = setupGtkBase(lib_gtk); + } + } + + if (gtkLoaded) { + load(lib_gtk, "gdk_init_check", gdk_init_check); + load(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data); + load(lib_gtk, "gtk_status_icon_new_from_pixbuf", gtk_status_icon_new_from_pixbuf); + load(lib_gtk, "gtk_status_icon_set_from_pixbuf", gtk_status_icon_set_from_pixbuf); + load(lib_gtk, "gtk_status_icon_set_title", gtk_status_icon_set_title); + load(lib_gtk, "gtk_status_icon_set_tooltip_text", gtk_status_icon_set_tooltip_text); + load(lib_gtk, "gtk_status_icon_set_visible", gtk_status_icon_set_visible); + load(lib_gtk, "gtk_status_icon_is_embedded", gtk_status_icon_is_embedded); + load(lib_gtk, "gtk_status_icon_get_geometry", gtk_status_icon_get_geometry); + load(lib_gtk, "gtk_status_icon_position_menu", gtk_status_icon_position_menu); + load(lib_gtk, "gtk_menu_popup", gtk_menu_popup); + load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time); + load(lib_gtk, "g_idle_add", g_idle_add); + } else { + LOG(("Could not load gtk-x11-2.0!")); + } + + if (QString(getenv("XDG_CURRENT_DESKTOP")).toLower() == qstr("unity")) { + QLibrary lib_unity(qstr("unity"), 9, 0); + loadLibrary(lib_unity, "unity", 9); + + load(lib_unity, "unity_launcher_entry_get_for_desktop_id", unity_launcher_entry_get_for_desktop_id); + load(lib_unity, "unity_launcher_entry_set_count", unity_launcher_entry_set_count); + load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible); + } +} + +} // namespace Libs +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.h b/Telegram/SourceFiles/platform/linux/linux_libs.h new file mode 100644 index 0000000000..83da7b6a8a --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_libs.h @@ -0,0 +1,174 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" + +#include + +namespace Platform { +namespace Libs { + +void start(); + +template +bool load(QLibrary &lib, const char *name, Function &func) { + func = nullptr; + if (!lib.isLoaded()) { + return false; + } + + func = reinterpret_cast(lib.resolve(name)); + if (func) { + return true; + } + LOG(("Error: failed to load '%1' function!").arg(name)); + return false; +} + +typedef gboolean (*f_gtk_init_check)(int *argc, char ***argv); +extern f_gtk_init_check gtk_init_check; + +typedef GtkWidget* (*f_gtk_menu_new)(void); +extern f_gtk_menu_new gtk_menu_new; + +typedef GType (*f_gtk_menu_get_type)(void) G_GNUC_CONST; +extern f_gtk_menu_get_type gtk_menu_get_type; + +typedef GtkWidget* (*f_gtk_menu_item_new_with_label)(const gchar *label); +extern f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label; + +typedef void (*f_gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label); +extern f_gtk_menu_item_set_label gtk_menu_item_set_label; + +typedef void (*f_gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child); +extern f_gtk_menu_shell_append gtk_menu_shell_append; + +typedef GType (*f_gtk_menu_shell_get_type)(void) G_GNUC_CONST; +extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type; + +typedef void (*f_gtk_widget_show)(GtkWidget *widget); +extern f_gtk_widget_show gtk_widget_show; + +typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget); +extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel; + +typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget); +extern f_gtk_widget_get_visible gtk_widget_get_visible; + +typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive); +extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive; + +typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type); +extern f_g_type_check_instance_cast g_type_check_instance_cast; + +template +inline Result *g_type_cic_helper(Object *instance, GType iface_type) { + return reinterpret_cast(g_type_check_instance_cast(reinterpret_cast(instance), iface_type)); +} +template +inline GtkMenu *gtk_menu_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_menu_get_type()); +} +template +inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_menu_get_type()); +} + +typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); +extern f_g_signal_connect_data g_signal_connect_data; +inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) { + return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0); +} + +typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category); +extern f_app_indicator_new app_indicator_new; + +typedef void (*f_app_indicator_set_status)(AppIndicator *self, AppIndicatorStatus status); +extern f_app_indicator_set_status app_indicator_set_status; + +typedef void (*f_app_indicator_set_menu)(AppIndicator *self, GtkMenu *menu); +extern f_app_indicator_set_menu app_indicator_set_menu; + +typedef void (*f_app_indicator_set_icon_full)(AppIndicator *self, const gchar *icon_name, const gchar *icon_desc); +extern f_app_indicator_set_icon_full app_indicator_set_icon_full; + +typedef gboolean (*f_gdk_init_check)(gint *argc, gchar ***argv); +extern f_gdk_init_check gdk_init_check; + +typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data); +extern f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data; + +typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf); +extern f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf; + +typedef void (*f_gtk_status_icon_set_from_pixbuf)(GtkStatusIcon *status_icon, GdkPixbuf *pixbuf); +extern f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf; + +typedef void (*f_gtk_status_icon_set_title)(GtkStatusIcon *status_icon, const gchar *title); +extern f_gtk_status_icon_set_title gtk_status_icon_set_title; + +typedef void (*f_gtk_status_icon_set_tooltip_text)(GtkStatusIcon *status_icon, const gchar *title); +extern f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text; + +typedef void (*f_gtk_status_icon_set_visible)(GtkStatusIcon *status_icon, gboolean visible); +extern f_gtk_status_icon_set_visible gtk_status_icon_set_visible; + +typedef gboolean (*f_gtk_status_icon_is_embedded)(GtkStatusIcon *status_icon); +extern f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded; + +typedef gboolean (*f_gtk_status_icon_get_geometry)(GtkStatusIcon *status_icon, GdkScreen **screen, GdkRectangle *area, GtkOrientation *orientation); +extern f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry; + +typedef void (*f_gtk_status_icon_position_menu)(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data); +extern f_gtk_status_icon_position_menu gtk_status_icon_position_menu; + +typedef void (*f_gtk_menu_popup)(GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time); +extern f_gtk_menu_popup gtk_menu_popup; + +typedef guint32 (*f_gtk_get_current_event_time)(void); +extern f_gtk_get_current_event_time gtk_get_current_event_time; + +typedef gpointer (*f_g_object_ref_sink)(gpointer object); +extern f_g_object_ref_sink g_object_ref_sink; + +typedef void (*f_g_object_unref)(gpointer object); +extern f_g_object_unref g_object_unref; + +typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data); +extern f_g_idle_add g_idle_add; + +typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value); +extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count; + +typedef void (*f_unity_launcher_entry_set_count_visible)(UnityLauncherEntry* self, gboolean value); +extern f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible; + +typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id); +extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id; + +} // namespace Libs +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index e0172a21b2..968854d2da 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "platform/linux/main_window_linux.h" +#include "platform/linux/linux_libs.h" #include "mainwindow.h" #include "application.h" #include "lang.h" @@ -29,10 +30,165 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Platform { namespace { +bool noQtTrayIcon = false, tryAppIndicator = false; +bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false; + +AppIndicator *_trayIndicator = 0; +GtkStatusIcon *_trayIcon = 0; +GtkWidget *_trayMenu = 0; +GdkPixbuf *_trayPixbuf = 0; +QByteArray _trayPixbufData; +QList > _trayItems; + +int32 _trayIconSize = 22; +bool _trayIconMuted = true; +int32 _trayIconCount = 0; +QImage _trayIconImageBack, _trayIconImage; + +void _trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popup_menu) { + Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, button, activate_time); +} + +void _trayIconActivate(GtkStatusIcon *status_icon, gpointer popup_menu) { + if (App::wnd()->isActiveWindow() && App::wnd()->isVisible()) { + Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, 0, Libs::gtk_get_current_event_time()); + } else { + App::wnd()->showFromTray(); + } +} + +gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_menu) { + _trayIconSize = size; + if (App::wnd()) App::wnd()->psUpdateCounter(); + return FALSE; +} + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + +#define QT_RED 3 +#define QT_GREEN 2 +#define QT_BLUE 1 +#define QT_ALPHA 0 + +#else + +#define QT_RED 0 +#define QT_GREEN 1 +#define QT_BLUE 2 +#define QT_ALPHA 3 + +#endif + +#define GTK_RED 2 +#define GTK_GREEN 1 +#define GTK_BLUE 0 +#define GTK_ALPHA 3 + +QImage _trayIconImageGen() { + int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; + bool muted = App::histories().unreadOnlyMuted(); + if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) { + if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) { + _trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + _trayIconImageBack = _trayIconImageBack.convertToFormat(QImage::Format_ARGB32); + int w = _trayIconImageBack.width(), h = _trayIconImageBack.height(), perline = _trayIconImageBack.bytesPerLine(); + uchar *bytes = _trayIconImageBack.bits(); + for (int32 y = 0; y < h; ++y) { + for (int32 x = 0; x < w; ++x) { + int32 srcoff = y * perline + x * 4; + bytes[srcoff + QT_RED ] = qMax(bytes[srcoff + QT_RED ], uchar(224)); + bytes[srcoff + QT_GREEN] = qMax(bytes[srcoff + QT_GREEN], uchar(165)); + bytes[srcoff + QT_BLUE ] = qMax(bytes[srcoff + QT_BLUE ], uchar(44)); + } + } + } + _trayIconImage = _trayIconImageBack; + if (counter > 0) { + QPainter p(&_trayIconImage); + int32 layerSize = -16; + if (_trayIconSize >= 48) { + layerSize = -32; + } else if (_trayIconSize >= 36) { + layerSize = -24; + } else if (_trayIconSize >= 32) { + layerSize = -20; + } + QImage layer = App::wnd()->iconWithCounter(layerSize, counter, (muted ? st::counterMuteBG : st::counterBG), false); + p.drawImage(_trayIconImage.width() - layer.width() - 1, _trayIconImage.height() - layer.height() - 1, layer); + } + } + return _trayIconImage; +} + +QString _trayIconImageFile() { + int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; + bool muted = App::histories().unreadOnlyMuted(); + + QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice); + QFileInfo info(name); + if (info.exists()) return name; + + QImage img = _trayIconImageGen(); + if (img.save(name, "PNG")) return name; + + QDir dir(info.absoluteDir()); + if (!dir.exists()) { + dir.mkpath(dir.absolutePath()); + if (img.save(name, "PNG")) return name; + } + + return QString(); +} + +void loadPixbuf(QImage image) { + int w = image.width(), h = image.height(), perline = image.bytesPerLine(), s = image.byteCount(); + _trayPixbufData.resize(w * h * 4); + uchar *result = (uchar*)_trayPixbufData.data(), *bytes = image.bits(); + for (int32 y = 0; y < h; ++y) { + for (int32 x = 0; x < w; ++x) { + int32 offset = (y * w + x) * 4, srcoff = y * perline + x * 4; + result[offset + GTK_RED ] = bytes[srcoff + QT_RED ]; + result[offset + GTK_GREEN] = bytes[srcoff + QT_GREEN]; + result[offset + GTK_BLUE ] = bytes[srcoff + QT_BLUE ]; + result[offset + GTK_ALPHA] = bytes[srcoff + QT_ALPHA]; + } + } + + if (_trayPixbuf) Libs::g_object_unref(_trayPixbuf); + _trayPixbuf = Libs::gdk_pixbuf_new_from_data(result, GDK_COLORSPACE_RGB, true, 8, w, h, w * 4, 0, 0); +} + +void _trayMenuCallback(GtkMenu *menu, gpointer data) { + for (int32 i = 0, l = _trayItems.size(); i < l; ++i) { + if ((void*)_trayItems.at(i).first == (void*)menu) { + QMetaObject::invokeMethod(_trayItems.at(i).second, "triggered"); + } + } +} + +static gboolean _trayIconCheck(gpointer/* pIn*/) { + if (useStatusIcon && !trayIconChecked) { + if (Libs::gtk_status_icon_is_embedded(_trayIcon)) { + trayIconChecked = true; + cSetSupportTray(true); + if (App::wnd()) { + App::wnd()->psUpdateWorkmode(); + App::wnd()->psUpdateCounter(); + App::wnd()->updateTrayMenu(); + } + } + } + return FALSE; +} + +UnityLauncherEntry *_psUnityLauncherEntry = nullptr; + } // namespace -MainWindow::MainWindow() : QMainWindow(), -posInited(false), trayIcon(0), trayIconMenu(0), icon256(qsl(":/gui/art/icon256.png")), iconbig256(icon256), wndIcon(QIcon::fromTheme("telegram", QIcon(QPixmap::fromImage(icon256, Qt::ColorOnly)))), _psCheckStatusIconLeft(100), _psLastIndicatorUpdate(0) { +MainWindow::MainWindow() +: icon256(qsl(":/gui/art/icon256.png")) +, iconbig256(icon256) +, wndIcon(QIcon::fromTheme("telegram", QIcon(QPixmap::fromImage(icon256, Qt::ColorOnly)))) { connect(&_psCheckStatusIconTimer, SIGNAL(timeout()), this, SLOT(psStatusIconCheck())); _psCheckStatusIconTimer.setSingleShot(false); @@ -64,11 +220,11 @@ void MainWindow::psTrayMenuUpdated() { if (_trayItems.isEmpty()) { DEBUG_LOG(("Creating tray menu!")); for (int32 i = 0, l = actions.size(); i != l; ++i) { - GtkWidget *item = ps_gtk_menu_item_new_with_label(actions.at(i)->text().toUtf8()); - ps_gtk_menu_shell_append(PS_GTK_MENU_SHELL(_trayMenu), item); - ps_g_signal_connect(item, "activate", G_CALLBACK(_trayMenuCallback), this); - ps_gtk_widget_show(item); - ps_gtk_widget_set_sensitive(item, actions.at(i)->isEnabled()); + GtkWidget *item = Libs::gtk_menu_item_new_with_label(actions.at(i)->text().toUtf8()); + Libs::gtk_menu_shell_append(Libs::gtk_menu_shell_cast(_trayMenu), item); + Libs::g_signal_connect_helper(item, "activate", G_CALLBACK(_trayMenuCallback), this); + Libs::gtk_widget_show(item); + Libs::gtk_widget_set_sensitive(item, actions.at(i)->isEnabled()); _trayItems.push_back(qMakePair(item, actions.at(i))); } @@ -76,8 +232,8 @@ void MainWindow::psTrayMenuUpdated() { DEBUG_LOG(("Updating tray menu!")); for (int32 i = 0, l = actions.size(); i != l; ++i) { if (i < _trayItems.size()) { - ps_gtk_menu_item_set_label(reinterpret_cast(_trayItems.at(i).first), actions.at(i)->text().toUtf8()); - ps_gtk_widget_set_sensitive(_trayItems.at(i).first, actions.at(i)->isEnabled()); + Libs::gtk_menu_item_set_label(reinterpret_cast(_trayItems.at(i).first), actions.at(i)->text().toUtf8()); + Libs::gtk_widget_set_sensitive(_trayItems.at(i).first, actions.at(i)->isEnabled()); } } } @@ -113,9 +269,9 @@ void MainWindow::psUpdateWorkmode() { if (cWorkMode() == dbiwmWindowOnly) { if (noQtTrayIcon) { if (useAppIndicator) { - ps_app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE); + Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE); } else if (useStatusIcon) { - ps_gtk_status_icon_set_visible(_trayIcon, false); + Libs::gtk_status_icon_set_visible(_trayIcon, false); } } else { if (trayIcon) { @@ -127,9 +283,9 @@ void MainWindow::psUpdateWorkmode() { } else { if (noQtTrayIcon) { if (useAppIndicator) { - ps_app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); + Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); } else if (useStatusIcon) { - ps_gtk_status_icon_set_visible(_trayIcon, true); + Libs::gtk_status_icon_set_visible(_trayIcon, true); } } else { psSetupTrayIcon(); @@ -144,7 +300,7 @@ void MainWindow::psUpdateIndicator() { if (f.exists()) { QByteArray path = QFile::encodeName(f.absoluteFilePath()), name = QFile::encodeName(f.fileName()); name = name.mid(0, name.size() - 4); - ps_app_indicator_set_icon_full(_trayIndicator, path.constData(), name); + Libs::app_indicator_set_icon_full(_trayIndicator, path.constData(), name); } else { useAppIndicator = false; } @@ -158,10 +314,10 @@ void MainWindow::psUpdateCounter() { setWindowTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); if (_psUnityLauncherEntry) { if (counter > 0) { - ps_unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter); - ps_unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, TRUE); + Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter); + Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, TRUE); } else { - ps_unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE); + Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE); } } @@ -174,7 +330,7 @@ void MainWindow::psUpdateCounter() { } } else if (useStatusIcon && trayIconChecked) { loadPixbuf(_trayIconImageGen()); - ps_gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); + Libs::gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); } } else if (trayIcon) { int32 counter = App::histories().unreadBadge(); @@ -188,6 +344,65 @@ void MainWindow::psUpdateCounter() { } } +void MainWindow::LibsLoaded() { + QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower(); + noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome")); + tryAppIndicator = (cdesktop == qstr("xfce")); + + if (noQtTrayIcon) cSetSupportTray(false); + + useGtkBase = (Libs::gtk_init_check != nullptr) + && (Libs::gtk_menu_new != nullptr) + && (Libs::gtk_menu_get_type != nullptr) + && (Libs::gtk_menu_item_new_with_label != nullptr) + && (Libs::gtk_menu_item_set_label != nullptr) + && (Libs::gtk_menu_shell_append != nullptr) + && (Libs::gtk_menu_shell_get_type != nullptr) + && (Libs::gtk_widget_show != nullptr) + && (Libs::gtk_widget_get_toplevel != nullptr) + && (Libs::gtk_widget_get_visible != nullptr) + && (Libs::gtk_widget_set_sensitive != nullptr) + && (Libs::g_type_check_instance_cast != nullptr) + && (Libs::g_signal_connect_data != nullptr) + && (Libs::g_object_ref_sink != nullptr) + && (Libs::g_object_unref != nullptr); + + useAppIndicator = useGtkBase + && (Libs::app_indicator_new != nullptr) + && (Libs::app_indicator_set_status != nullptr) + && (Libs::app_indicator_set_menu != nullptr) + && (Libs::app_indicator_set_icon_full != nullptr); + + if (tryAppIndicator && useGtkBase && useAppIndicator) { + noQtTrayIcon = true; + cSetSupportTray(false); + } + + useStatusIcon = (Libs::gdk_init_check != nullptr) + && (Libs::gdk_pixbuf_new_from_data != nullptr) + && (Libs::gtk_status_icon_new_from_pixbuf != nullptr) + && (Libs::gtk_status_icon_set_from_pixbuf != nullptr) + && (Libs::gtk_status_icon_set_title != nullptr) + && (Libs::gtk_status_icon_set_tooltip_text != nullptr) + && (Libs::gtk_status_icon_set_visible != nullptr) + && (Libs::gtk_status_icon_is_embedded != nullptr) + && (Libs::gtk_status_icon_get_geometry != nullptr) + && (Libs::gtk_status_icon_position_menu != nullptr) + && (Libs::gtk_menu_popup != nullptr) + && (Libs::gtk_get_current_event_time != nullptr) + && (Libs::g_idle_add != nullptr); + if (useStatusIcon) { + DEBUG_LOG(("Status icon api loaded!")); + } + + useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr) + && (Libs::unity_launcher_entry_set_count != nullptr) + && (Libs::unity_launcher_entry_set_count_visible != nullptr); + if (useUnityCount) { + DEBUG_LOG(("Unity count api loaded!")); + } +} + void MainWindow::psUpdateDelegate() { } @@ -228,10 +443,6 @@ void MainWindow::psInitSize() { void MainWindow::psInitFrameless() { psUpdatedPositionTimer.setSingleShot(true); connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); - - if (frameless) { - //setWindowFlags(Qt::FramelessWindowHint); - } } void MainWindow::psSavePosition(Qt::WindowState state) { @@ -289,13 +500,13 @@ void MainWindow::psCreateTrayIcon() { if (useAppIndicator) { DEBUG_LOG(("Trying to create AppIndicator")); - _trayMenu = ps_gtk_menu_new(); + _trayMenu = Libs::gtk_menu_new(); if (_trayMenu) { DEBUG_LOG(("Created gtk menu for appindicator!")); QFileInfo f(_trayIconImageFile()); if (f.exists()) { QByteArray path = QFile::encodeName(f.absoluteFilePath()); - _trayIndicator = ps_app_indicator_new("Telegram Desktop", path.constData(), APP_INDICATOR_CATEGORY_APPLICATION_STATUS); + _trayIndicator = Libs::app_indicator_new("Telegram Desktop", path.constData(), APP_INDICATOR_CATEGORY_APPLICATION_STATUS); if (_trayIndicator) { DEBUG_LOG(("Created appindicator!")); } else { @@ -309,8 +520,8 @@ void MainWindow::psCreateTrayIcon() { DEBUG_LOG(("Failed to gtk_menu_new()!")); } if (_trayMenu && _trayIndicator) { - ps_app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); - ps_app_indicator_set_menu(_trayIndicator, PS_GTK_MENU(_trayMenu)); + Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); + Libs::app_indicator_set_menu(_trayIndicator, Libs::gtk_menu_cast(_trayMenu)); useStatusIcon = false; } else { DEBUG_LOG(("AppIndicator failed!")); @@ -318,19 +529,19 @@ void MainWindow::psCreateTrayIcon() { } } if (useStatusIcon) { - if (ps_gdk_init_check(0, 0)) { - if (!_trayMenu) _trayMenu = ps_gtk_menu_new(); + if (Libs::gdk_init_check(0, 0)) { + if (!_trayMenu) _trayMenu = Libs::gtk_menu_new(); if (_trayMenu) { loadPixbuf(_trayIconImageGen()); - _trayIcon = ps_gtk_status_icon_new_from_pixbuf(_trayPixbuf); + _trayIcon = Libs::gtk_status_icon_new_from_pixbuf(_trayPixbuf); if (_trayIcon) { - ps_g_signal_connect(_trayIcon, "popup-menu", GCallback(_trayIconPopup), _trayMenu); - ps_g_signal_connect(_trayIcon, "activate", GCallback(_trayIconActivate), _trayMenu); - ps_g_signal_connect(_trayIcon, "size-changed", GCallback(_trayIconResized), _trayMenu); + Libs::g_signal_connect_helper(_trayIcon, "popup-menu", GCallback(_trayIconPopup), _trayMenu); + Libs::g_signal_connect_helper(_trayIcon, "activate", GCallback(_trayIconActivate), _trayMenu); + Libs::g_signal_connect_helper(_trayIcon, "size-changed", GCallback(_trayIconResized), _trayMenu); - ps_gtk_status_icon_set_title(_trayIcon, "Telegram Desktop"); - ps_gtk_status_icon_set_tooltip_text(_trayIcon, "Telegram Desktop"); - ps_gtk_status_icon_set_visible(_trayIcon, true); + Libs::gtk_status_icon_set_title(_trayIcon, "Telegram Desktop"); + Libs::gtk_status_icon_set_tooltip_text(_trayIcon, "Telegram Desktop"); + Libs::gtk_status_icon_set_visible(_trayIcon, true); } else { useStatusIcon = false; } @@ -343,14 +554,14 @@ void MainWindow::psCreateTrayIcon() { } if (!useStatusIcon && !useAppIndicator) { if (_trayMenu) { - ps_g_object_ref_sink(_trayMenu); - ps_g_object_unref(_trayMenu); + Libs::g_object_ref_sink(_trayMenu); + Libs::g_object_unref(_trayMenu); _trayMenu = 0; } } cSetSupportTray(useAppIndicator); if (useStatusIcon) { - ps_g_idle_add((GSourceFunc)_trayIconCheck, 0); + Libs::g_idle_add((GSourceFunc)_trayIconCheck, 0); _psCheckStatusIconTimer.start(100); } else { psUpdateWorkmode(); @@ -361,11 +572,11 @@ void MainWindow::psFirstShow() { psCreateTrayIcon(); if (useUnityCount) { - _psUnityLauncherEntry = ps_unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop"); + _psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop"); if (_psUnityLauncherEntry) { LOG(("Found Unity Launcher entry telegramdesktop.desktop!")); } else { - _psUnityLauncherEntry = ps_unity_launcher_entry_get_for_desktop_id("Telegram.desktop"); + _psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("Telegram.desktop"); if (_psUnityLauncherEntry) { LOG(("Found Unity Launcher entry Telegram.desktop!")); } else { @@ -376,8 +587,6 @@ void MainWindow::psFirstShow() { LOG(("Not using Unity Launcher count.")); } - finished = false; - psUpdateMargins(); bool showShadows = true; @@ -419,21 +628,32 @@ void MainWindow::psUpdateMargins() { void MainWindow::psFlash() { } +void MainWindow::psActivateNotify(NotifyWindow *w) { +} + +void MainWindow::psClearNotifies(PeerId peerId) { +} + +void MainWindow::psNotifyShown(NotifyWindow *w) { +} + +void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { +} + MainWindow::~MainWindow() { if (_trayIcon) { - ps_g_object_unref(_trayIcon); - _trayIcon = 0; + Libs::g_object_unref(_trayIcon); + _trayIcon = nullptr; } if (_trayPixbuf) { - ps_g_object_unref(_trayPixbuf); - _trayPixbuf = 0; + Libs::g_object_unref(_trayPixbuf); + _trayPixbuf = nullptr; } if (_trayMenu) { - ps_g_object_ref_sink(_trayMenu); - ps_g_object_unref(_trayMenu); - _trayMenu = 0; + Libs::g_object_ref_sink(_trayMenu); + Libs::g_object_unref(_trayMenu); + _trayMenu = nullptr; } - finished = true; } } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 946a739392..2526a9c5fc 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -71,6 +71,8 @@ public: virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0; + static void LibsLoaded(); + ~MainWindow(); public slots: @@ -86,9 +88,9 @@ protected: bool psHasTrayIcon() const; - bool posInited; - QSystemTrayIcon *trayIcon; - QMenu *trayIconMenu; + bool posInited = false; + QSystemTrayIcon *trayIcon = nullptr; + QMenu *trayIconMenu = nullptr; QImage icon256, iconbig256; QIcon wndIcon; @@ -101,10 +103,10 @@ private: void psCreateTrayIcon(); QTimer _psCheckStatusIconTimer; - int _psCheckStatusIconLeft; + int _psCheckStatusIconLeft = 100; QTimer _psUpdateIndicatorTimer; - uint64 _psLastIndicatorUpdate; + uint64 _psLastIndicatorUpdate = 0; }; } // namespace Platform diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index bd7ce62ce2..f5e880cace 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -18,6 +18,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "pspecific.h" +#include "platform/linux/linux_libs.h" #include "lang.h" #include "application.h" #include "mainwidget.h" @@ -33,14 +34,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include -extern "C" { -#undef signals -#include -#include -#define signals public -} // extern "C" - -#include +using namespace Platform; namespace { QByteArray escapeShell(const QByteArray &str) { @@ -66,422 +60,6 @@ namespace { return result; } - bool frameless = true; - bool finished = true; - bool noQtTrayIcon = false, noTryUnity = false, tryAppIndicator = false; - bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false; - - AppIndicator *_trayIndicator = 0; - GtkStatusIcon *_trayIcon = 0; - GtkWidget *_trayMenu = 0; - GdkPixbuf *_trayPixbuf = 0; - QByteArray _trayPixbufData; - QList > _trayItems; - - int32 _trayIconSize = 22; - bool _trayIconMuted = true; - int32 _trayIconCount = 0; - QImage _trayIconImageBack, _trayIconImage; - - typedef gboolean (*f_gtk_init_check)(int *argc, char ***argv); - f_gtk_init_check ps_gtk_init_check = 0; - - typedef GtkWidget* (*f_gtk_menu_new)(void); - f_gtk_menu_new ps_gtk_menu_new = 0; - - typedef GType (*f_gtk_menu_get_type)(void) G_GNUC_CONST; - f_gtk_menu_get_type ps_gtk_menu_get_type = 0; - - typedef GtkWidget* (*f_gtk_menu_item_new_with_label)(const gchar *label); - f_gtk_menu_item_new_with_label ps_gtk_menu_item_new_with_label = 0; - - typedef void (*f_gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label); - f_gtk_menu_item_set_label ps_gtk_menu_item_set_label = 0; - - typedef void (*f_gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child); - f_gtk_menu_shell_append ps_gtk_menu_shell_append = 0; - - typedef GType (*f_gtk_menu_shell_get_type)(void) G_GNUC_CONST; - f_gtk_menu_shell_get_type ps_gtk_menu_shell_get_type = 0; - - typedef void (*f_gtk_widget_show)(GtkWidget *widget); - f_gtk_widget_show ps_gtk_widget_show = 0; - - typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget); - f_gtk_widget_get_toplevel ps_gtk_widget_get_toplevel = 0; - - typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget); - f_gtk_widget_get_visible ps_gtk_widget_get_visible = 0; - - typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive); - f_gtk_widget_set_sensitive ps_gtk_widget_set_sensitive = 0; - - typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type); - f_g_type_check_instance_cast ps_g_type_check_instance_cast = 0; - -#define _PS_G_TYPE_CIC(ip, gt, ct) ((ct*)ps_g_type_check_instance_cast((GTypeInstance*) ip, gt)) -#define PS_G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_PS_G_TYPE_CIC((instance), (g_type), c_type)) -#define PS_GTK_TYPE_MENU (ps_gtk_menu_get_type()) -#define PS_GTK_MENU(obj) (PS_G_TYPE_CHECK_INSTANCE_CAST((obj), PS_GTK_TYPE_MENU, GtkMenu)) -#define PS_GTK_TYPE_MENU_SHELL (ps_gtk_menu_shell_get_type()) -#define PS_GTK_MENU_SHELL(obj) (PS_G_TYPE_CHECK_INSTANCE_CAST((obj), PS_GTK_TYPE_MENU_SHELL, GtkMenuShell)) - - typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); - f_g_signal_connect_data ps_g_signal_connect_data = 0; - -#define ps_g_signal_connect(instance, detailed_signal, c_handler, data) ps_g_signal_connect_data((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags)0) - - typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category); - f_app_indicator_new ps_app_indicator_new = 0; - - typedef void (*f_app_indicator_set_status)(AppIndicator *self, AppIndicatorStatus status); - f_app_indicator_set_status ps_app_indicator_set_status = 0; - - typedef void (*f_app_indicator_set_menu)(AppIndicator *self, GtkMenu *menu); - f_app_indicator_set_menu ps_app_indicator_set_menu = 0; - - typedef void (*f_app_indicator_set_icon_full)(AppIndicator *self, const gchar *icon_name, const gchar *icon_desc); - f_app_indicator_set_icon_full ps_app_indicator_set_icon_full = 0; - - typedef gboolean (*f_gdk_init_check)(gint *argc, gchar ***argv); - f_gdk_init_check ps_gdk_init_check = 0; - - typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data); - f_gdk_pixbuf_new_from_data ps_gdk_pixbuf_new_from_data = 0; - - typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf); - f_gtk_status_icon_new_from_pixbuf ps_gtk_status_icon_new_from_pixbuf = 0; - - typedef void (*f_gtk_status_icon_set_from_pixbuf)(GtkStatusIcon *status_icon, GdkPixbuf *pixbuf); - f_gtk_status_icon_set_from_pixbuf ps_gtk_status_icon_set_from_pixbuf = 0; - - typedef void (*f_gtk_status_icon_set_title)(GtkStatusIcon *status_icon, const gchar *title); - f_gtk_status_icon_set_title ps_gtk_status_icon_set_title = 0; - - typedef void (*f_gtk_status_icon_set_tooltip_text)(GtkStatusIcon *status_icon, const gchar *title); - f_gtk_status_icon_set_tooltip_text ps_gtk_status_icon_set_tooltip_text = 0; - - typedef void (*f_gtk_status_icon_set_visible)(GtkStatusIcon *status_icon, gboolean visible); - f_gtk_status_icon_set_visible ps_gtk_status_icon_set_visible = 0; - - typedef gboolean (*f_gtk_status_icon_is_embedded)(GtkStatusIcon *status_icon); - f_gtk_status_icon_is_embedded ps_gtk_status_icon_is_embedded = 0; - - typedef gboolean (*f_gtk_status_icon_get_geometry)(GtkStatusIcon *status_icon, GdkScreen **screen, GdkRectangle *area, GtkOrientation *orientation); - f_gtk_status_icon_get_geometry ps_gtk_status_icon_get_geometry = 0; - - typedef void (*f_gtk_status_icon_position_menu)(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data); - f_gtk_status_icon_position_menu ps_gtk_status_icon_position_menu = 0; - - typedef void (*f_gtk_menu_popup)(GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time); - f_gtk_menu_popup ps_gtk_menu_popup = 0; - - typedef guint32 (*f_gtk_get_current_event_time)(void); - f_gtk_get_current_event_time ps_gtk_get_current_event_time = 0; - - typedef gpointer (*f_g_object_ref_sink)(gpointer object); - f_g_object_ref_sink ps_g_object_ref_sink = 0; - - typedef void (*f_g_object_unref)(gpointer object); - f_g_object_unref ps_g_object_unref = 0; - - typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data); - f_g_idle_add ps_g_idle_add = 0; - - typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value); - f_unity_launcher_entry_set_count ps_unity_launcher_entry_set_count = 0; - - typedef void (*f_unity_launcher_entry_set_count_visible)(UnityLauncherEntry* self, gboolean value); - f_unity_launcher_entry_set_count_visible ps_unity_launcher_entry_set_count_visible = 0; - - typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id); - f_unity_launcher_entry_get_for_desktop_id ps_unity_launcher_entry_get_for_desktop_id = 0; - - template - bool loadFunction(QLibrary &lib, const char *name, TFunction &func) { - if (!lib.isLoaded()) return false; - - func = (TFunction)lib.resolve(name); - if (func) { - return true; - } else { - LOG(("Error: failed to load '%1' function!").arg(name)); - return false; - } - } - - void _trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popup_menu) { - ps_gtk_menu_popup(PS_GTK_MENU(popup_menu), NULL, NULL, ps_gtk_status_icon_position_menu, status_icon, button, activate_time); - } - - void _trayIconActivate(GtkStatusIcon *status_icon, gpointer popup_menu) { - if (App::wnd()->isActiveWindow() && App::wnd()->isVisible()) { - ps_gtk_menu_popup(PS_GTK_MENU(popup_menu), NULL, NULL, ps_gtk_status_icon_position_menu, status_icon, 0, ps_gtk_get_current_event_time()); - } else { - App::wnd()->showFromTray(); - } - } - - gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_menu) { - _trayIconSize = size; - if (App::wnd()) App::wnd()->psUpdateCounter(); - return FALSE; - } - -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - -#define QT_RED 3 -#define QT_GREEN 2 -#define QT_BLUE 1 -#define QT_ALPHA 0 - -#else - -#define QT_RED 0 -#define QT_GREEN 1 -#define QT_BLUE 2 -#define QT_ALPHA 3 - -#endif - -#define GTK_RED 2 -#define GTK_GREEN 1 -#define GTK_BLUE 0 -#define GTK_ALPHA 3 - - QImage _trayIconImageGen() { - int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; - bool muted = App::histories().unreadOnlyMuted(); - if (_trayIconImage.isNull() || _trayIconImage.width() != _trayIconSize || muted != _trayIconMuted || counterSlice != _trayIconCount) { - if (_trayIconImageBack.isNull() || _trayIconImageBack.width() != _trayIconSize) { - _trayIconImageBack = App::wnd()->iconLarge().scaled(_trayIconSize, _trayIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - _trayIconImageBack = _trayIconImageBack.convertToFormat(QImage::Format_ARGB32); - int w = _trayIconImageBack.width(), h = _trayIconImageBack.height(), perline = _trayIconImageBack.bytesPerLine(); - uchar *bytes = _trayIconImageBack.bits(); - for (int32 y = 0; y < h; ++y) { - for (int32 x = 0; x < w; ++x) { - int32 srcoff = y * perline + x * 4; - bytes[srcoff + QT_RED ] = qMax(bytes[srcoff + QT_RED ], uchar(224)); - bytes[srcoff + QT_GREEN] = qMax(bytes[srcoff + QT_GREEN], uchar(165)); - bytes[srcoff + QT_BLUE ] = qMax(bytes[srcoff + QT_BLUE ], uchar(44)); - } - } - } - _trayIconImage = _trayIconImageBack; - if (counter > 0) { - QPainter p(&_trayIconImage); - int32 layerSize = -16; - if (_trayIconSize >= 48) { - layerSize = -32; - } else if (_trayIconSize >= 36) { - layerSize = -24; - } else if (_trayIconSize >= 32) { - layerSize = -20; - } - QImage layer = App::wnd()->iconWithCounter(layerSize, counter, (muted ? st::counterMuteBG : st::counterBG), false); - p.drawImage(_trayIconImage.width() - layer.width() - 1, _trayIconImage.height() - layer.height() - 1, layer); - } - } - return _trayIconImage; - } - - QString _trayIconImageFile() { - int32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; - bool muted = App::histories().unreadOnlyMuted(); - - QString name = cWorkingDir() + qsl("tdata/ticons/ico%1_%2_%3.png").arg(muted ? "mute" : "").arg(_trayIconSize).arg(counterSlice); - QFileInfo info(name); - if (info.exists()) return name; - - QImage img = _trayIconImageGen(); - if (img.save(name, "PNG")) return name; - - QDir dir(info.absoluteDir()); - if (!dir.exists()) { - dir.mkpath(dir.absolutePath()); - if (img.save(name, "PNG")) return name; - } - - return QString(); - } - - void loadPixbuf(QImage image) { - int w = image.width(), h = image.height(), perline = image.bytesPerLine(), s = image.byteCount(); - _trayPixbufData.resize(w * h * 4); - uchar *result = (uchar*)_trayPixbufData.data(), *bytes = image.bits(); - for (int32 y = 0; y < h; ++y) { - for (int32 x = 0; x < w; ++x) { - int32 offset = (y * w + x) * 4, srcoff = y * perline + x * 4; - result[offset + GTK_RED ] = bytes[srcoff + QT_RED ]; - result[offset + GTK_GREEN] = bytes[srcoff + QT_GREEN]; - result[offset + GTK_BLUE ] = bytes[srcoff + QT_BLUE ]; - result[offset + GTK_ALPHA] = bytes[srcoff + QT_ALPHA]; - } - } - - if (_trayPixbuf) ps_g_object_unref(_trayPixbuf); - _trayPixbuf = ps_gdk_pixbuf_new_from_data(result, GDK_COLORSPACE_RGB, true, 8, w, h, w * 4, 0, 0); - } - - void _trayMenuCallback(GtkMenu *menu, gpointer data) { - for (int32 i = 0, l = _trayItems.size(); i < l; ++i) { - if ((void*)_trayItems.at(i).first == (void*)menu) { - QMetaObject::invokeMethod(_trayItems.at(i).second, "triggered"); - } - } - } - - static gboolean _trayIconCheck(gpointer/* pIn*/) { - if (useStatusIcon && !trayIconChecked) { - if (ps_gtk_status_icon_is_embedded(_trayIcon)) { - trayIconChecked = true; - cSetSupportTray(true); - if (App::wnd()) { - App::wnd()->psUpdateWorkmode(); - App::wnd()->psUpdateCounter(); - App::wnd()->updateTrayMenu(); - } - } - } - return FALSE; - } - - bool loadLibrary(QLibrary &lib, const char *name, int version) { - DEBUG_LOG(("Loading '%1' with version %2...").arg(QLatin1String(name)).arg(version)); - lib.setFileNameAndVersion(QLatin1String(name), version); - if (lib.load()) { - DEBUG_LOG(("Loaded '%1' with version %2!").arg(QLatin1String(name)).arg(version)); - return true; - } - lib.setFileNameAndVersion(QLatin1String(name), QString()); - if (lib.load()) { - DEBUG_LOG(("Loaded '%1' without version!").arg(QLatin1String(name))); - return true; - } - LOG(("Could not load '%1' with version %2 :(").arg(QLatin1String(name)).arg(version)); - return false; - } - - void setupGtkBase(QLibrary &lib_gtk) { - if (!loadFunction(lib_gtk, "gtk_init_check", ps_gtk_init_check)) return; - if (!loadFunction(lib_gtk, "gtk_menu_new", ps_gtk_menu_new)) return; - if (!loadFunction(lib_gtk, "gtk_menu_get_type", ps_gtk_menu_get_type)) return; - - if (!loadFunction(lib_gtk, "gtk_menu_item_new_with_label", ps_gtk_menu_item_new_with_label)) return; - if (!loadFunction(lib_gtk, "gtk_menu_item_set_label", ps_gtk_menu_item_set_label)) return; - if (!loadFunction(lib_gtk, "gtk_menu_shell_append", ps_gtk_menu_shell_append)) return; - if (!loadFunction(lib_gtk, "gtk_menu_shell_get_type", ps_gtk_menu_shell_get_type)) return; - if (!loadFunction(lib_gtk, "gtk_widget_show", ps_gtk_widget_show)) return; - if (!loadFunction(lib_gtk, "gtk_widget_get_toplevel", ps_gtk_widget_get_toplevel)) return; - if (!loadFunction(lib_gtk, "gtk_widget_get_visible", ps_gtk_widget_get_visible)) return; - if (!loadFunction(lib_gtk, "gtk_widget_set_sensitive", ps_gtk_widget_set_sensitive)) return; - - if (!loadFunction(lib_gtk, "g_type_check_instance_cast", ps_g_type_check_instance_cast)) return; - if (!loadFunction(lib_gtk, "g_signal_connect_data", ps_g_signal_connect_data)) return; - - if (!loadFunction(lib_gtk, "g_object_ref_sink", ps_g_object_ref_sink)) return; - if (!loadFunction(lib_gtk, "g_object_unref", ps_g_object_unref)) return; - - DEBUG_LOG(("Library gtk functions loaded!")); - if (ps_gtk_init_check(0, 0)) { - DEBUG_LOG(("Checked gtk with gtk_init_check!")); - useGtkBase = true; - } else { - DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); - } - } - - void setupAppIndicator(QLibrary &lib_indicator) { - if (!loadFunction(lib_indicator, "app_indicator_new", ps_app_indicator_new)) return; - if (!loadFunction(lib_indicator, "app_indicator_set_status", ps_app_indicator_set_status)) return; - if (!loadFunction(lib_indicator, "app_indicator_set_menu", ps_app_indicator_set_menu)) return; - if (!loadFunction(lib_indicator, "app_indicator_set_icon_full", ps_app_indicator_set_icon_full)) return; - useAppIndicator = true; - DEBUG_LOG(("Library appindicator functions loaded!")); - } - - void setupGtk() { - QLibrary lib_gtk, lib_indicator; - if (!noQtTrayIcon && !tryAppIndicator) { - if (!noTryUnity) { - if (loadLibrary(lib_gtk, "gtk-3", 0)) { - setupGtkBase(lib_gtk); - } - if (!useGtkBase) { - if (loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { - setupGtkBase(lib_gtk); - } - } - if (!useGtkBase) { - noTryUnity = true; - } - } - return; - } - - if (loadLibrary(lib_indicator, "appindicator3", 1)) { - if (loadLibrary(lib_gtk, "gtk-3", 0)) { - setupGtkBase(lib_gtk); - setupAppIndicator(lib_indicator); - } - } - if (!useGtkBase || !useAppIndicator) { - if (loadLibrary(lib_indicator, "appindicator", 1)) { - if (loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { - useGtkBase = useAppIndicator = false; - setupGtkBase(lib_gtk); - setupAppIndicator(lib_indicator); - } - } - } - if (tryAppIndicator) { - if (useGtkBase && useAppIndicator) { - noQtTrayIcon = true; - cSetSupportTray(false); - } - return; - } - - if (!useGtkBase && lib_gtk.isLoaded()) { - LOG(("Could not load appindicator, trying to load gtk...")); - setupGtkBase(lib_gtk); - } - if (!useGtkBase) { - useAppIndicator = false; - LOG(("Could not load gtk-x11-2.0!")); - return; - } - - if (!loadFunction(lib_gtk, "gdk_init_check", ps_gdk_init_check)) return; - if (!loadFunction(lib_gtk, "gdk_pixbuf_new_from_data", ps_gdk_pixbuf_new_from_data)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_new_from_pixbuf", ps_gtk_status_icon_new_from_pixbuf)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_set_from_pixbuf", ps_gtk_status_icon_set_from_pixbuf)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_set_title", ps_gtk_status_icon_set_title)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_set_tooltip_text", ps_gtk_status_icon_set_tooltip_text)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_set_visible", ps_gtk_status_icon_set_visible)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_is_embedded", ps_gtk_status_icon_is_embedded)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_get_geometry", ps_gtk_status_icon_get_geometry)) return; - if (!loadFunction(lib_gtk, "gtk_status_icon_position_menu", ps_gtk_status_icon_position_menu)) return; - if (!loadFunction(lib_gtk, "gtk_menu_popup", ps_gtk_menu_popup)) return; - if (!loadFunction(lib_gtk, "gtk_get_current_event_time", ps_gtk_get_current_event_time)) return; - if (!loadFunction(lib_gtk, "g_idle_add", ps_g_idle_add)) return; - useStatusIcon = true; - DEBUG_LOG(("Status icon api loaded!")); - } - - void setupUnity() { - if (noTryUnity) return; - - QLibrary lib_unity(qstr("unity"), 9, 0); - if (!loadLibrary(lib_unity, "unity", 9)) return; - - if (!loadFunction(lib_unity, "unity_launcher_entry_get_for_desktop_id", ps_unity_launcher_entry_get_for_desktop_id)) return; - if (!loadFunction(lib_unity, "unity_launcher_entry_set_count", ps_unity_launcher_entry_set_count)) return; - if (!loadFunction(lib_unity, "unity_launcher_entry_set_count_visible", ps_unity_launcher_entry_set_count_visible)) return; - useUnityCount = true; - DEBUG_LOG(("Unity count api loaded!")); - } - class _PsEventFilter : public QAbstractNativeEventFilter { public: _PsEventFilter() { @@ -495,8 +73,6 @@ namespace { } }; _PsEventFilter *_psEventFilter = 0; - - UnityLauncherEntry *_psUnityLauncherEntry = 0; }; namespace { @@ -521,18 +97,6 @@ void psBringToBack(QWidget *w) { w->hide(); } -void PsMainWindow::psActivateNotify(NotifyWindow *w) { -} - -void PsMainWindow::psClearNotifies(PeerId peerId) { -} - -void PsMainWindow::psNotifyShown(NotifyWindow *w) { -} - -void PsMainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) { -} - QAbstractNativeEventFilter *psNativeEventFilter() { delete _psEventFilter; _psEventFilter = new _PsEventFilter(); @@ -842,16 +406,8 @@ void finish() { namespace ThirdParty { void start() { - QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower(); - noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome")); - tryAppIndicator = (cdesktop == qstr("xfce")); - noTryUnity = (cdesktop != qstr("unity")); - - if (noQtTrayIcon) cSetSupportTray(false); - - DEBUG_LOG(("Loading libraries")); - setupGtk(); - setupUnity(); + Libs::start(); + MainWindow::LibsLoaded(); } void finish() { diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index 5115c16d2d..5aec57778a 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -80,14 +80,14 @@ TitleWidget::TitleWidget(MainWindow *window) : TWidget(window) ) { showUpdateBtn(); } - stateChanged(); + onWindowStateChanged(); connect(&_back, SIGNAL(clicked()), window, SLOT(hideSettings())); connect(&_cancel, SIGNAL(clicked()), this, SIGNAL(hiderClicked())); connect(&_settings, SIGNAL(clicked()), window, SLOT(showSettings())); connect(&_contacts, SIGNAL(clicked()), this, SLOT(onContacts())); connect(&_about, SIGNAL(clicked()), this, SLOT(onAbout())); - connect(wnd->windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(stateChanged(Qt::WindowState))); + connect(wnd->windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onWindowStateChanged(Qt::WindowState))); #ifndef TDESKTOP_DISABLE_AUTOUPDATE Sandbox::connect(SIGNAL(updateReady()), this, SLOT(showUpdateBtn())); @@ -308,7 +308,7 @@ void TitleWidget::mouseDoubleClickEvent(QMouseEvent *e) { } } -void TitleWidget::stateChanged(Qt::WindowState state) { +void TitleWidget::onWindowStateChanged(Qt::WindowState state) { if (state == Qt::WindowMinimized) return; maximizedChanged(state == Qt::WindowMaximized); } diff --git a/Telegram/SourceFiles/title.h b/Telegram/SourceFiles/title.h index a0cf522269..e6ef17cc57 100644 --- a/Telegram/SourceFiles/title.h +++ b/Telegram/SourceFiles/title.h @@ -67,7 +67,7 @@ public: public slots: - void stateChanged(Qt::WindowState state = Qt::WindowNoState); + void onWindowStateChanged(Qt::WindowState state = Qt::WindowNoState); void showUpdateBtn(); void onContacts(); void onAbout(); diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index b2824c378d..321ae0d44f 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -19,8 +19,6 @@ CONFIG(release, debug|release) { macx { QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist - OBJECTIVE_SOURCES += ./SourceFiles/pspecific_mac_p.mm - OBJECTIVE_HEADERS += ./SourceFiles/pspecific_mac_p.h QMAKE_LFLAGS += -framework Cocoa } @@ -160,6 +158,8 @@ SOURCES += \ ./SourceFiles/mtproto/scheme_auto.cpp \ ./SourceFiles/mtproto/session.cpp \ ./SourceFiles/overview/overview_layout.cpp \ + ./SourceFiles/platform/linux/linux_libs.cpp \ + ./SourceFiles/platform/linux/main_window_linux.cpp \ ./SourceFiles/profile/profile_actions_widget.cpp \ ./SourceFiles/profile/profile_block_widget.cpp \ ./SourceFiles/profile/profile_cover_drop_area.cpp \ @@ -206,6 +206,7 @@ SOURCES += \ ./SourceFiles/ui/images.cpp \ ./SourceFiles/ui/scrollarea.cpp \ ./SourceFiles/ui/twidget.cpp \ + ./SourceFiles/window/main_window.cpp \ ./SourceFiles/window/section_widget.cpp \ ./SourceFiles/window/slide_animation.cpp \ ./SourceFiles/window/top_bar_widget.cpp @@ -312,6 +313,9 @@ HEADERS += \ ./SourceFiles/mtproto/scheme_auto.h \ ./SourceFiles/mtproto/session.h \ ./SourceFiles/overview/overview_layout.h \ + ./SourceFiles/platform/platform_main_window.h \ + ./SourceFiles/platform/linux/linux_libs.h \ + ./SourceFiles/platform/linux/main_window_linux.h \ ./SourceFiles/profile/profile_actions_widget.h \ ./SourceFiles/profile/profile_block_widget.h \ ./SourceFiles/profile/profile_cover_drop_area.h \ @@ -359,6 +363,7 @@ HEADERS += \ ./SourceFiles/ui/images.h \ ./SourceFiles/ui/scrollarea.h \ ./SourceFiles/ui/twidget.h \ + ./SourceFiles/window/main_window.h \ ./SourceFiles/window/section_memento.h \ ./SourceFiles/window/section_widget.h \ ./SourceFiles/window/slide_animation.h \ @@ -366,16 +371,27 @@ HEADERS += \ win32 { SOURCES += \ - ./SourceFiles/pspecific_win.cpp + ./SourceFiles/pspecific_win.cpp \ + ./SourceFiles/platform/win/windows_app_user_model_id.cpp \ + ./SourceFiles/platform/win/windows_dlls.cpp \ + ./SourceFiles/platform/win/windows_event_filter.cpp \ + ./SourceFiles/platform/win/windows_toasts.cpp + HEADERS += \ - ./SourceFiles/pspecific_win.h + ./SourceFiles/pspecific_win.h \ + ./SourceFiles/platform/win/windows_app_user_model_id.h \ + ./SourceFiles/platform/win/windows_dlls.h \ + ./SourceFiles/platform/win/windows_event_filter.h \ + ./SourceFiles/platform/win/windows_toasts.h } winrt { SOURCES += \ - ./SourceFiles/pspecific_winrt.cpp + ./SourceFiles/pspecific_winrt.cpp \ + ./SourceFiles/platform/winrt/main_window_winrt.cpp HEADERS += \ - ./SourceFiles/pspecific_winrt.h + ./SourceFiles/pspecific_winrt.h \ + ./Sourcefiles/platform/winrt/main_window_winrt.h } macx { @@ -383,6 +399,12 @@ SOURCES += \ ./SourceFiles/pspecific_mac.cpp HEADERS += \ ./SourceFiles/pspecific_mac.h +OBJECTIVE_SOURCES += \ + ./SourceFiles/pspecific_mac_p.mm \ + ./SourceFiles/platform/mac/main_window_mac.mm +HEADERS += \ + ./SourceFiles/pspecific_mac_p.h \ + ./SourceFiles/platform/mac/main_window_mac.h } SOURCES += \