1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Merge branch 'statusnotifier'

This commit is contained in:
tux3 2015-02-22 01:46:43 +01:00
commit 49295c8c48
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
11 changed files with 2789 additions and 4 deletions

View File

@ -74,6 +74,23 @@ contains(ENABLE_SYSTRAY_UNITY_BACKEND, YES) {
LIBS += -lgobject-2.0 -lappindicator -lgtk-x11-2.0
}
contains(ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND, YES) {
DEFINES += ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
INCLUDEPATH += "/usr/include/atk-1.0"
LIBS += -lglib-2.0 -lgdk_pixbuf-2.0 -lgio-2.0 -lcairo -lgtk-x11-2.0 -lgdk-x11-2.0 -lgobject-2.0
}
android {
ANDROID_TOOLCHAIN=/opt/android/toolchain-r9d-17/
INCLUDEPATH += $$ANDROID_TOOLCHAIN/include/
@ -249,7 +266,11 @@ HEADERS += src/widget/form/addfriendform.h \
src/nexus.h \
src/widget/gui.h \
src/widget/androidgui.h \
src/offlinemsgengine.h
src/offlinemsgengine.h \
src/platform/statusnotifier/closures.h \
src/platform/statusnotifier/enums.h \
src/platform/statusnotifier/interfaces.h \
src/platform/statusnotifier/statusnotifier.h
SOURCES += \
src/widget/form/addfriendform.cpp \
@ -328,7 +349,10 @@ SOURCES += \
src/nexus.cpp \
src/widget/gui.cpp \
src/widget/androidgui.cpp \
src/offlinemsgengine.cpp
src/offlinemsgengine.cpp \
src/platform/statusnotifier/closures.c \
src/platform/statusnotifier/enums.c \
src/platform/statusnotifier/statusnotifier.c
contains(DEFINES, QTOX_FILTER_AUDIO) {
HEADERS += src/audiofilterer.h

View File

@ -0,0 +1,114 @@
/*
* statusnotifier - Copyright (C) 2014 Olivier Brunel
*
* closures.c
* Copyright (C) 2014 Olivier Brunel <jjk@jjacky.com>
*
* This file is part of statusnotifier.
*
* statusnotifier 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.
*
* statusnotifier 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
* statusnotifier. If not, see http://www.gnu.org/licenses/
*/
#include <glib-object.h>
#include "closures.h"
#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
#define g_marshal_value_peek_int(v) g_value_get_int (v)
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
#define g_marshal_value_peek_long(v) g_value_get_long (v)
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
#define g_marshal_value_peek_float(v) g_value_get_float (v)
#define g_marshal_value_peek_double(v) g_value_get_double (v)
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v) g_value_get_param (v)
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
#define g_marshal_value_peek_object(v) g_value_get_object (v)
#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
* Do not access GValues directly in your code. Instead, use the
* g_value_get_*() functions
*/
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */
/* BOOLEAN:INT,INT (closures.def:1) */
void
g_cclosure_user_marshal_BOOLEAN__INT_INT (GClosure *closure,
GValue *return_value G_GNUC_UNUSED,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint G_GNUC_UNUSED,
gpointer marshal_data)
{
typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT) (gpointer data1,
gint arg_1,
gint arg_2,
gpointer data2);
register GMarshalFunc_BOOLEAN__INT_INT callback;
register GCClosure *cc = (GCClosure*) closure;
register gpointer data1, data2;
gboolean v_return;
g_return_if_fail (return_value != NULL);
g_return_if_fail (n_param_values == 3);
if (G_CCLOSURE_SWAP_DATA (closure))
{
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
}
else
{
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback = (GMarshalFunc_BOOLEAN__INT_INT) (marshal_data ? marshal_data : cc->callback);
v_return = callback (data1,
g_marshal_value_peek_int (param_values + 1),
g_marshal_value_peek_int (param_values + 2),
data2);
g_value_set_boolean (return_value, v_return);
}

View File

@ -0,0 +1,41 @@
/*
* statusnotifier - Copyright (C) 2014 Olivier Brunel
*
* closures.h
* Copyright (C) 2014 Olivier Brunel <jjk@jjacky.com>
*
* This file is part of statusnotifier.
*
* statusnotifier 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.
*
* statusnotifier 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
* statusnotifier. If not, see http://www.gnu.org/licenses/
*/
#ifndef __g_cclosure_user_marshal_MARSHAL_H__
#define __g_cclosure_user_marshal_MARSHAL_H__
#include <glib-object.h>
G_BEGIN_DECLS
/* BOOLEAN:INT,INT (closures.def:1) */
extern void g_cclosure_user_marshal_BOOLEAN__INT_INT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
G_END_DECLS
#endif /* __g_cclosure_user_marshal_MARSHAL_H__ */

View File

@ -0,0 +1,101 @@
#include "enums.h"
GType
status_notifier_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_ERROR_NO_CONNECTION, "STATUS_NOTIFIER_ERROR_NO_CONNECTION", "connection" },
{ STATUS_NOTIFIER_ERROR_NO_NAME, "STATUS_NOTIFIER_ERROR_NO_NAME", "name" },
{ STATUS_NOTIFIER_ERROR_NO_WATCHER, "STATUS_NOTIFIER_ERROR_NO_WATCHER", "watcher" },
{ STATUS_NOTIFIER_ERROR_NO_HOST, "STATUS_NOTIFIER_ERROR_NO_HOST", "host" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierError", values);
}
return etype;
}
GType
status_notifier_state_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_STATE_NOT_REGISTERED, "STATUS_NOTIFIER_STATE_NOT_REGISTERED", "not-registered" },
{ STATUS_NOTIFIER_STATE_REGISTERING, "STATUS_NOTIFIER_STATE_REGISTERING", "registering" },
{ STATUS_NOTIFIER_STATE_REGISTERED, "STATUS_NOTIFIER_STATE_REGISTERED", "registered" },
{ STATUS_NOTIFIER_STATE_FAILED, "STATUS_NOTIFIER_STATE_FAILED", "failed" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierState", values);
}
return etype;
}
GType
status_notifier_icon_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_ICON, "STATUS_NOTIFIER_ICON", "status-notifier-icon" },
{ STATUS_NOTIFIER_ATTENTION_ICON, "STATUS_NOTIFIER_ATTENTION_ICON", "status-notifier-attention-icon" },
{ STATUS_NOTIFIER_OVERLAY_ICON, "STATUS_NOTIFIER_OVERLAY_ICON", "status-notifier-overlay-icon" },
{ STATUS_NOTIFIER_TOOLTIP_ICON, "STATUS_NOTIFIER_TOOLTIP_ICON", "status-notifier-tooltip-icon" },
{ _NB_STATUS_NOTIFIER_ICONS, "_NB_STATUS_NOTIFIER_ICONS", "-nb-status-notifier-icons" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierIcon", values);
}
return etype;
}
GType
status_notifier_category_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS, "STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS", "application-status" },
{ STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS, "STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS", "communications" },
{ STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES, "STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES", "system-services" },
{ STATUS_NOTIFIER_CATEGORY_HARDWARE, "STATUS_NOTIFIER_CATEGORY_HARDWARE", "hardware" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierCategory", values);
}
return etype;
}
GType
status_notifier_status_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_STATUS_PASSIVE, "STATUS_NOTIFIER_STATUS_PASSIVE", "passive" },
{ STATUS_NOTIFIER_STATUS_ACTIVE, "STATUS_NOTIFIER_STATUS_ACTIVE", "active" },
{ STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION, "STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION", "needs-attention" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierStatus", values);
}
return etype;
}
GType
status_notifier_scroll_orientation_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
{ STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL, "STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL", "horizontal" },
{ STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL, "STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL", "vertical" },
{ 0, NULL, NULL }
};
etype = g_enum_register_static ("StatusNotifierScrollOrientation", values);
}
return etype;
}

View File

@ -0,0 +1,24 @@
#ifndef __STATUS_NOTIFIER_ENUMS_H__
#define __STATUS_NOTIFIER_ENUMS_H__
#include "statusnotifier.h"
GType status_notifier_error_get_type (void);
#define TYPE_STATUS_NOTIFIER_ERROR (status_notifier_error_get_type())
GType status_notifier_state_get_type (void);
#define TYPE_STATUS_NOTIFIER_STATE (status_notifier_state_get_type())
GType status_notifier_icon_get_type (void);
#define TYPE_STATUS_NOTIFIER_ICON (status_notifier_icon_get_type())
GType status_notifier_category_get_type (void);
#define TYPE_STATUS_NOTIFIER_CATEGORY (status_notifier_category_get_type())
GType status_notifier_status_get_type (void);
#define TYPE_STATUS_NOTIFIER_STATUS (status_notifier_status_get_type())
GType status_notifier_scroll_orientation_get_type (void);
#define TYPE_STATUS_NOTIFIER_SCROLL_ORIENTATION (status_notifier_scroll_orientation_get_type())
G_END_DECLS
#endif /* __STATUS_NOTIFIER_ENUMS_H__ */

View File

@ -0,0 +1,94 @@
/*
* statusnotifier - Copyright (C) 2014 Olivier Brunel
*
* interfaces.h
* Copyright (C) 2014 Olivier Brunel <jjk@jjacky.com>
*
* This file is part of statusnotifier.
*
* statusnotifier 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.
*
* statusnotifier 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
* statusnotifier. If not, see http://www.gnu.org/licenses/
*/
#ifndef __INTERFACES_H__
#define __INTERFACES_H__
G_BEGIN_DECLS
#define WATCHER_NAME "org.kde.StatusNotifierWatcher"
#define WATCHER_OBJECT "/StatusNotifierWatcher"
#define WATCHER_INTERFACE "org.kde.StatusNotifierWatcher"
#define ITEM_NAME "org.kde.StatusNotifierItem"
#define ITEM_OBJECT "/StatusNotifierItem"
#define ITEM_INTERFACE "org.kde.StatusNotifierItem"
static const gchar watcher_xml[] =
"<node>"
" <interface name='org.kde.StatusNotifierWatcher'>"
" <property name='IsStatusNotifierHostRegistered' type='b' access='read' />"
" <method name='RegisterStatusNotifierItem'>"
" <arg name='service' type='s' direction='in' />"
" </method>"
" <signal name='StatusNotifierHostRegistered' />"
" <signal name='StatusNotifierHostUnregistered' />"
" </interface>"
"</node>";
static const gchar item_xml[] =
"<node>"
" <interface name='org.kde.StatusNotifierItem'>"
" <property name='Id' type='s' access='read' />"
" <property name='Category' type='s' access='read' />"
" <property name='Title' type='s' access='read' />"
" <property name='Status' type='s' access='read' />"
" <property name='WindowId' type='i' access='read' />"
" <property name='IconName' type='s' access='read' />"
" <property name='IconPixmap' type='(iiay)' access='read' />"
" <property name='OverlayIconName' type='s' access='read' />"
" <property name='OverlayIconPixmap' type='(iiay)' access='read' />"
" <property name='AttentionIconName' type='s' access='read' />"
" <property name='AttentionIconPixmap' type='(iiay)' access='read' />"
" <property name='AttentionMovieName' type='s' access='read' />"
" <property name='ToolTip' type='(s(iiay)ss)' access='read' />"
" <method name='ContextMenu'>"
" <arg name='x' type='i' direction='in' />"
" <arg name='y' type='i' direction='in' />"
" </method>"
" <method name='Activate'>"
" <arg name='x' type='i' direction='in' />"
" <arg name='y' type='i' direction='in' />"
" </method>"
" <method name='SecondaryActivate'>"
" <arg name='x' type='i' direction='in' />"
" <arg name='y' type='i' direction='in' />"
" </method>"
" <method name='Scroll'>"
" <arg name='delta' type='i' direction='in' />"
" <arg name='orientation' type='s' direction='in' />"
" </method>"
" <signal name='NewTitle' />"
" <signal name='NewIcon' />"
" <signal name='NewAttentionIcon' />"
" <signal name='NewOverlayIcon' />"
" <signal name='NewToolTip' />"
" <signal name='NewStatus'>"
" <arg name='status' type='s' />"
" </signal>"
" </interface>"
"</node>";
G_END_DECLS
#endif /* __INTERFACES_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,304 @@
/*
* statusnotifier - Copyright (C) 2014 Olivier Brunel
*
* statusnotifier.h
* Copyright (C) 2014 Olivier Brunel <jjk@jjacky.com>
*
* This file is part of statusnotifier.
*
* statusnotifier 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.
*
* statusnotifier 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
* statusnotifier. If not, see http://www.gnu.org/licenses/
*/
#ifndef __STATUS_NOTIFIER_H__
#define __STATUS_NOTIFIER_H__
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
typedef struct _StatusNotifier StatusNotifier;
typedef struct _StatusNotifierPrivate StatusNotifierPrivate;
typedef struct _StatusNotifierClass StatusNotifierClass;
#define TYPE_STATUS_NOTIFIER (status_notifier_get_type ())
#define STATUS_NOTIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_STATUS_NOTIFIER, StatusNotifier))
#define STATUS_NOTIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_STATUS_NOTIFIER, StatusNotiferClass))
#define IS_STATUS_NOTIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_STATUS_NOTIFIER))
#define IS_STATUS_NOTIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TYPE_STATUS_NOTIFIER))
#define STATUS_NOTIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_STATUS_NOTIFIER, StatusNotifierClass))
GType status_notifier_get_type (void) G_GNUC_CONST;
#define STATUS_NOTIFIER_ERROR g_quark_from_static_string ("StatusNotifier error")
/**
* StatusNotifierError:
* @STATUS_NOTIFIER_ERROR_NO_CONNECTION: Failed to establish connection to
* register service on session bus
* @STATUS_NOTIFIER_ERROR_NO_NAME: Failed to acquire name for the item on the
* session bus
* @STATUS_NOTIFIER_ERROR_NO_WATCHER: No StatusNotifierWatcher found on the
* session bus
* @STATUS_NOTIFIER_ERROR_NO_HOST: No StatusNotifierHost registered with the
* StatusNotifierWatcher
*
* Errors that can occur while trying to register the item. Note that errors
* other the #StatusNotifierError might be returned.
*/
typedef enum
{
STATUS_NOTIFIER_ERROR_NO_CONNECTION = 0,
STATUS_NOTIFIER_ERROR_NO_NAME,
STATUS_NOTIFIER_ERROR_NO_WATCHER,
STATUS_NOTIFIER_ERROR_NO_HOST
} StatusNotifierError;
/**
* StatusNotifierState:
* @STATUS_NOTIFIER_STATE_NOT_REGISTERED: Item hasn't yet been asked to
* register, i.e. no call to status_notifier_register() have been made yet
* @STATUS_NOTIFIER_STATE_REGISTERING: Item is in the process of registering.
* This state is also valid after #StatusNotifier::registration-failed was
* emitted, if the item is waiting for possible "recovery" (e.g. if no host was
* registered on watcher, waiting for one to do so)
* @STATUS_NOTIFIER_STATE_REGISTERED: Item was sucessfully registered on DBus
* and StatusNotifierWatcher
* @STATUS_NOTIFIER_STATE_FAILED: Registration failed, with no possible pending
* recovery
*
* State in which a #StatusNotifier item can be. See status_notifier_register()
* for more
*/
typedef enum
{
STATUS_NOTIFIER_STATE_NOT_REGISTERED = 0,
STATUS_NOTIFIER_STATE_REGISTERING,
STATUS_NOTIFIER_STATE_REGISTERED,
STATUS_NOTIFIER_STATE_FAILED
} StatusNotifierState;
/**
* StatusNotifierIcon:
* @STATUS_NOTIFIER_ICON: The icon that can be used by the visualization to
* identify the item.
* @STATUS_NOTIFIER_ATTENTION_ICON: The icon that can be used by the
* visualization when the item's status is
* %STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION.
* @STATUS_NOTIFIER_OVERLAY_ICON: This can be used by the visualization to
* indicate extra state information, for instance as an overlay for the main
* icon.
* @STATUS_NOTIFIER_TOOLTIP_ICON: The icon that can be used be the visualization
* in the tooltip of the item.
*
* Possible icons that can be used on a status notifier item.
*/
typedef enum
{
STATUS_NOTIFIER_ICON = 0,
STATUS_NOTIFIER_ATTENTION_ICON,
STATUS_NOTIFIER_OVERLAY_ICON,
STATUS_NOTIFIER_TOOLTIP_ICON,
/*< private >*/
_NB_STATUS_NOTIFIER_ICONS
} StatusNotifierIcon;
/**
* StatusNotifierCategory:
* @STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS: The item describes the status
* of a generic application, for instance the current state of a media player.
* In the case where the category of the item can not be known, such as when the
* item is being proxied from another incompatible or emulated system, this can
* be used a sensible default fallback.
* @STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS: The item describes the status of
* communication oriented applications, like an instant messenger or an email
* client.
* @STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES: The item describes services of the
* system not seen as a stand alone application by the user, such as an
* indicator for the activity of a disk indexing service.
* @STATUS_NOTIFIER_CATEGORY_HARDWARE: The item describes the state and control
* of a particular hardware, such as an indicator of the battery charge or sound
* card volume control.
*
* The category of the status notifier item.
*/
typedef enum
{
STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS = 0,
STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS,
STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES,
STATUS_NOTIFIER_CATEGORY_HARDWARE
} StatusNotifierCategory;
/**
* StatusNotifierStatus:
* @STATUS_NOTIFIER_STATUS_PASSIVE: The item doesn't convey important
* information to the user, it can be considered an "idle" status and is likely
* that visualizations will chose to hide it.
* @STATUS_NOTIFIER_STATUS_ACTIVE: The item is active, is more important that
* the item will be shown in some way to the user.
* @STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION: The item carries really important
* information for the user, such as battery charge running out and is wants to
* incentive the direct user intervention. Visualizations should emphasize in
* some way the items with this status.
*
* The status of the status notifier item or its associated application.
*/
typedef enum
{
STATUS_NOTIFIER_STATUS_PASSIVE = 0,
STATUS_NOTIFIER_STATUS_ACTIVE,
STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION
} StatusNotifierStatus;
/**
* StatusNotifierScrollOrientation:
* @STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL: Scroll request was
* horizontal.
* @STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL: Scroll request was vertical.
*
* The orientation of a scroll request performed on the representation of the
* item in the visualization.
*/
typedef enum
{
STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL = 0,
STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL
} StatusNotifierScrollOrientation;
struct _StatusNotifier
{
/*< private >*/
GObject parent;
StatusNotifierPrivate *priv;
};
/**
* StatusNotifierClass:
* @parent_class: Parent class
* @registration_failed: When registering the item failed, e.g. because there's
* no StatusNotifierHost registered (yet); If this occurs, you should fallback
* to using the systray
* @context_menu: Item should show a context menu, this is typically a
* consequence of user input, such as mouse right click over the graphical
* representation of the item.
* @activate: Activation of the item was requested, this is typically a
* consequence of user input, such as mouse left click over the graphical
* representation of the item.
* @secondary_activate: Secondary and less important form of activation
* (compared to @activate) of the item was requested. This is typically a
* consequence of user input, such as mouse middle click over the graphical
* representation of the item.
* @scroll: The user asked for a scroll action. This is caused from input such
* as mouse wheel over the graphical representation of the item.
*/
struct _StatusNotifierClass
{
GObjectClass parent_class;
/* signals */
void (*registration_failed) (StatusNotifier *sn,
GError *error);
gboolean (*context_menu) (StatusNotifier *sn,
gint x,
gint y);
gboolean (*activate) (StatusNotifier *sn,
gint x,
gint y);
gboolean (*secondary_activate) (StatusNotifier *sn,
gint x,
gint y);
gboolean (*scroll) (StatusNotifier *sn,
gint delta,
StatusNotifierScrollOrientation orientation);
};
StatusNotifier * status_notifier_new_from_pixbuf (
const gchar *id,
StatusNotifierCategory category,
GdkPixbuf *pixbuf);
StatusNotifier * status_notifier_new_from_icon_name (
const gchar *id,
StatusNotifierCategory category,
const gchar *icon_name);
const gchar * status_notifier_get_id (
StatusNotifier *sn);
StatusNotifierCategory status_notifier_get_category (
StatusNotifier *sn);
void status_notifier_set_from_pixbuf (
StatusNotifier *sn,
StatusNotifierIcon icon,
GdkPixbuf *pixbuf);
void status_notifier_set_from_icon_name (
StatusNotifier *sn,
StatusNotifierIcon icon,
const gchar *icon_name);
gboolean status_notifier_has_pixbuf (
StatusNotifier *sn,
StatusNotifierIcon icon);
GdkPixbuf * status_notifier_get_pixbuf (
StatusNotifier *sn,
StatusNotifierIcon icon);
gchar * status_notifier_get_icon_name (
StatusNotifier *sn,
StatusNotifierIcon icon);
void status_notifier_set_attention_movie_name (
StatusNotifier *sn,
const gchar *movie_name);
gchar * status_notifier_get_attention_movie_name (
StatusNotifier *sn);
void status_notifier_set_title (
StatusNotifier *sn,
const gchar *title);
gchar * status_notifier_get_title (
StatusNotifier *sn);
void status_notifier_set_status (
StatusNotifier *sn,
StatusNotifierStatus status);
StatusNotifierStatus status_notifier_get_status (
StatusNotifier *sn);
void status_notifier_set_window_id (
StatusNotifier *sn,
guint32 window_id);
guint32 status_notifier_get_window_id (
StatusNotifier *sn);
void status_notifier_freeze_tooltip (
StatusNotifier *sn);
void status_notifier_thaw_tooltip (
StatusNotifier *sn);
void status_notifier_set_tooltip (
StatusNotifier *sn,
const gchar *icon_name,
const gchar *title,
const gchar *body);
void status_notifier_set_tooltip_title (
StatusNotifier *sn,
const gchar *title);
gchar * status_notifier_get_tooltip_title (
StatusNotifier *sn);
void status_notifier_set_tooltip_body (
StatusNotifier *sn,
const gchar *body);
gchar * status_notifier_get_tooltip_body (
StatusNotifier *sn);
void status_notifier_register (
StatusNotifier *sn);
StatusNotifierState status_notifier_get_state (
StatusNotifier *sn);
G_END_DECLS
#endif /* __STATUS_NOTIFIER_H__ */

View File

@ -34,6 +34,29 @@ SystemTrayIcon::SystemTrayIcon()
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
}
#endif
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (true)
{
backendType = SystrayBackendType::StatusNotifier;
gtk_init(nullptr, nullptr);
snMenu = gtk_menu_new();
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(":/img/icon.png");
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
statusNotifier = status_notifier_new_from_pixbuf("qtox",
STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS, pixbuf);
status_notifier_register(statusNotifier);
}
#endif
else if (desktop.toLower() == "kde"
&& getenv("KDE_SESSION_VERSION") == QString("5"))
{
@ -69,12 +92,69 @@ QString SystemTrayIcon::extractIconToFile(QIcon icon, QString name)
void SystemTrayIcon::setContextMenu(QMenu* menu)
{
if (false);
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier)
{
void (*callbackClick)(StatusNotifier*, gint, gint, gpointer) =
[](StatusNotifier*, gint, gint, gpointer data)
{
((SystemTrayIcon*)data)->activated(QSystemTrayIcon::Trigger);
};
g_signal_connect(statusNotifier, "activate", G_CALLBACK(callbackClick), this);
void (*callbackMiddleClick)(StatusNotifier*, gint, gint, gpointer) =
[](StatusNotifier*, gint, gint, gpointer data)
{
((SystemTrayIcon*)data)->activated(QSystemTrayIcon::MiddleClick);
};
g_signal_connect(statusNotifier, "secondary_activate", G_CALLBACK(callbackMiddleClick), this);
for (QAction* a : menu->actions())
{
QString aText = a->text().replace('&',"");
GtkWidget* item;
if (a->isSeparator())
item = gtk_menu_item_new();
else if (a->icon().isNull())
item = gtk_menu_item_new_with_label(aText.toStdString().c_str());
else
{
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(a->icon().pixmap(64, 64).toImage());
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
item = gtk_image_menu_item_new_with_label(aText.toStdString().c_str());
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), gtk_image_new_from_pixbuf(pixbuf));
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item),TRUE);
}
gtk_menu_shell_append(GTK_MENU_SHELL(snMenu), item);
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a)
{
((QAction*)a)->activate(QAction::Trigger);
};
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
gtk_widget_show(item);
}
void (*callbackMenu)(StatusNotifier*, gint, gint, gpointer) =
[](StatusNotifier*, gint, gint, gpointer data)
{
gtk_widget_show_all(((SystemTrayIcon*)data)->snMenu);
gtk_menu_popup(GTK_MENU(((SystemTrayIcon*)data)->snMenu), 0, 0, 0, 0, 3, gtk_get_current_event_time());
};
g_signal_connect(statusNotifier, "context-menu", G_CALLBACK(callbackMenu), this);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity)
{
for (QAction* a : menu->actions())
{
gtk_image_menu_item_new();
QString aText = a->text().replace('&',"");
GtkWidget* item;
if (a->isSeparator())
@ -129,6 +209,15 @@ void SystemTrayIcon::hide()
void SystemTrayIcon::setVisible(bool newState)
{
if (false);
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier)
{
if (newState)
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_ACTIVE);
else
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_PASSIVE);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity)
{
@ -150,6 +239,23 @@ void SystemTrayIcon::setVisible(bool newState)
void SystemTrayIcon::setIcon(QIcon &&icon)
{
if (false);
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier)
{
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(icon.pixmap(64, 64).toImage());
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
status_notifier_set_from_pixbuf(statusNotifier, STATUS_NOTIFIER_ICON, pixbuf);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity)
{

View File

@ -32,6 +32,10 @@ private:
AppIndicator *unityIndicator;
GtkWidget *unityMenu;
#endif
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
StatusNotifier* statusNotifier;
GtkWidget* snMenu;
#endif
};
#endif // SYSTEMTRAYICON_H

View File

@ -3,6 +3,21 @@
#include <QSystemTrayIcon>
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
#ifdef signals
#undef signals
#endif
extern "C" {
#include <gtk/gtk.h>
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "src/platform/statusnotifier/statusnotifier.h"
}
#define signals public
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
#ifdef signals
#undef signals
@ -20,7 +35,10 @@ enum class SystrayBackendType
Qt,
KDE5,
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
Unity
Unity,
#endif
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
StatusNotifier,
#endif
};