mirror of
https://github.com/ukui/ukui-indicators.git
synced 2026-10-23 06:48:48 -07:00
239 lines
7.5 KiB
C++
239 lines
7.5 KiB
C++
/*
|
|
* Copyright (C) 2016, Tianjin KYLIN Information Technology Co., Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "indicator-desktop.h"
|
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
|
|
#include <libwnck/libwnck.h>
|
|
#undef WNCK_I_KNOW_THIS_IS_UNSTABLE
|
|
|
|
class IndicatorDesktop;
|
|
|
|
static void show_desktop_changed_cb(WnckScreen* screen, IndicatorDesktop *d);
|
|
static gboolean on_button_press(GtkWidget* widget, GdkEventButton* event, IndicatorDesktop *d);
|
|
static gboolean on_button_release(GtkWidget* widget, GdkEventButton* event, IndicatorDesktop *d);
|
|
static gboolean button_hover_callback(GtkWidget *event_box, GdkEvent *event, IndicatorDesktop *d);
|
|
static void applet_size_changed(UkuiPanelApplet *applet, guint size, IndicatorDesktop *d);
|
|
|
|
static const double WidthHeightRatio = 0.4;
|
|
static const int HoverDelay = 400; // wait for 400ms to trigger showing desktop
|
|
static WnckScreen *wnck_screen = NULL;
|
|
|
|
IndicatorDesktop::IndicatorDesktop(AppletData *ad) :
|
|
applet(ad->applet),
|
|
image(NULL),
|
|
orientation(ad->orientation),
|
|
has_cursor(FALSE),
|
|
hover_blocked(FALSE),
|
|
showing_desktop(FALSE)
|
|
{
|
|
size = ukui_panel_applet_get_size(applet);
|
|
change_size_handler_id = g_signal_connect(applet, "change_size",
|
|
G_CALLBACK(applet_size_changed), this);
|
|
|
|
if (wnck_screen == NULL)
|
|
wnck_screen = wnck_screen_get_default();
|
|
|
|
if (wnck_screen)
|
|
show_desktop_changed_handle_id = g_signal_connect(wnck_screen, "showing-desktop-changed",
|
|
G_CALLBACK(show_desktop_changed_cb), this);
|
|
else
|
|
g_warning("Could not get WnckScreen");
|
|
show_desktop_changed_cb(wnck_screen, this);
|
|
|
|
image = gtk_image_new_from_pixbuf(NULL);
|
|
set_button_state(StateNormal);
|
|
|
|
g_signal_connect(applet, "change_size", G_CALLBACK(applet_size_changed), this);
|
|
|
|
event_box = gtk_event_box_new();
|
|
g_signal_connect(event_box, "button-press-event", G_CALLBACK(on_button_press), this);
|
|
g_signal_connect(event_box, "button-release-event", G_CALLBACK(on_button_release), this);
|
|
g_signal_connect(event_box, "enter-notify-event", G_CALLBACK(button_hover_callback), this);
|
|
g_signal_connect(event_box, "leave-notify-event", G_CALLBACK(button_hover_callback), this);
|
|
|
|
// gtk_widget_set_tooltip_text(event_box, "显示桌面");
|
|
gtk_container_add(GTK_CONTAINER(event_box), image);
|
|
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE);
|
|
gtk_widget_show_all(event_box);
|
|
}
|
|
|
|
IndicatorDesktop::~IndicatorDesktop()
|
|
{
|
|
g_signal_handler_disconnect(wnck_screen, show_desktop_changed_handle_id);
|
|
g_signal_handler_disconnect(applet, change_size_handler_id);
|
|
}
|
|
|
|
void IndicatorDesktop::set_button_state(AppletState state)
|
|
{
|
|
GdkPixbuf *pixbuf = NULL;
|
|
GdkPixbuf *scaled = NULL;
|
|
|
|
if (image == NULL)
|
|
return;
|
|
|
|
if (state == StateHovered)
|
|
pixbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR"/show-desktop-hovered.png", NULL);
|
|
else if (state == StatePressed)
|
|
pixbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR"/show-desktop-pressed.png", NULL);
|
|
else
|
|
pixbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR"/show-desktop-normal.png", NULL);
|
|
|
|
if (orientation == GTK_ORIENTATION_HORIZONTAL) {
|
|
scaled = gdk_pixbuf_scale_simple(pixbuf, size * WidthHeightRatio, size, GDK_INTERP_BILINEAR);
|
|
gtk_widget_set_size_request(image, size * WidthHeightRatio, size);
|
|
} else {
|
|
scaled = gdk_pixbuf_scale_simple(pixbuf, size, size * WidthHeightRatio, GDK_INTERP_BILINEAR);
|
|
gtk_widget_set_size_request(image, size, size * WidthHeightRatio);
|
|
}
|
|
|
|
gtk_image_set_from_pixbuf(GTK_IMAGE(image), scaled);
|
|
|
|
g_object_unref(scaled);
|
|
g_object_unref(pixbuf);
|
|
}
|
|
|
|
static void
|
|
show_desktop_changed_cb(WnckScreen* screen, IndicatorDesktop *d)
|
|
{
|
|
if (wnck_screen)
|
|
d->showing_desktop = wnck_screen_get_showing_desktop(wnck_screen);
|
|
|
|
if (d->showing_desktop == FALSE) {
|
|
d->set_button_state(StateNormal);
|
|
d->hover_blocked = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
show_desktop(IndicatorDesktop *d, gboolean show)
|
|
{
|
|
static GtkWidget* dialog = NULL;
|
|
|
|
GtkWidget *button = d->event_box;
|
|
|
|
if (!gdk_x11_screen_supports_net_wm_hint(gtk_widget_get_screen(button), gdk_atom_intern("_NET_SHOWING_DESKTOP", FALSE))) {
|
|
if (dialog && gtk_widget_get_screen(dialog) != gtk_widget_get_screen(button))
|
|
gtk_widget_destroy (dialog);
|
|
|
|
if (dialog) {
|
|
gtk_window_present(GTK_WINDOW(dialog));
|
|
return;
|
|
}
|
|
|
|
dialog = gtk_message_dialog_new(NULL,
|
|
GTK_DIALOG_MODAL,
|
|
GTK_MESSAGE_ERROR,
|
|
GTK_BUTTONS_CLOSE,
|
|
"显示桌面出错,请检查窗口管理器是否支持_NET_SHOWING_DESKTOP");
|
|
|
|
g_object_add_weak_pointer(G_OBJECT(dialog), (gpointer *) &dialog);
|
|
|
|
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL);
|
|
|
|
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
|
|
gtk_window_set_screen(GTK_WINDOW(dialog), gtk_widget_get_screen(button));
|
|
gtk_widget_show(dialog);
|
|
|
|
return;
|
|
}
|
|
|
|
if (wnck_screen)
|
|
wnck_screen_toggle_showing_desktop(wnck_screen, show);
|
|
}
|
|
|
|
static gboolean
|
|
on_button_press(GtkWidget* widget, GdkEventButton* event, IndicatorDesktop *d)
|
|
{
|
|
if (event->button != 1)
|
|
return TRUE;
|
|
|
|
d->set_button_state(StatePressed);
|
|
|
|
if (d->showing_desktop) {
|
|
if (d->hover_blocked)
|
|
show_desktop(d, FALSE);
|
|
else
|
|
d->hover_blocked = TRUE;
|
|
} else {
|
|
show_desktop(d, TRUE);
|
|
d->hover_blocked = TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
applet_size_changed(UkuiPanelApplet *applet, guint size, IndicatorDesktop *d)
|
|
{
|
|
d->size = size;
|
|
d->set_button_state(StateNormal);
|
|
}
|
|
|
|
static gboolean
|
|
on_button_release(GtkWidget* widget, GdkEventButton* event, IndicatorDesktop *d)
|
|
{
|
|
if (event->button != 1)
|
|
return FALSE;
|
|
|
|
if (d->hover_blocked)
|
|
return FALSE;
|
|
|
|
d->set_button_state(StateHovered);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
timeout_callback(IndicatorDesktop *d)
|
|
{
|
|
if (d->has_cursor == FALSE) {
|
|
return FALSE;
|
|
}
|
|
show_desktop(d, TRUE);
|
|
|
|
// always return FALSE since this should be a single shot timer
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
button_hover_callback(GtkWidget *event_box, GdkEvent *event, IndicatorDesktop *d)
|
|
{
|
|
if (d->hover_blocked)
|
|
return FALSE;
|
|
|
|
if (event->type == GDK_ENTER_NOTIFY) {
|
|
d->set_button_state(StateHovered);
|
|
|
|
d->has_cursor = TRUE;
|
|
g_timeout_add(HoverDelay, GSourceFunc(timeout_callback), d);
|
|
}
|
|
if (event->type == GDK_LEAVE_NOTIFY) {
|
|
d->set_button_state(StateNormal);
|
|
|
|
d->has_cursor = FALSE;
|
|
show_desktop(d, FALSE);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|