Skip to content
Snippets Groups Projects
power-manager-button.c 59.2 KiB
Newer Older
Eric Koegel's avatar
Eric Koegel committed
 * * Copyright (C) 2014 Eric Koegel <eric@xfce.org>
 * * Copyright (C) 2019 Kacper Piwiński
 *
 * Licensed under the GNU General Public License Version 2
 *
 * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <glib.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfce4ui/libxfce4ui.h>
#include <upower.h>
#include <xfconf/xfconf.h>

#include "common/xfpm-common.h"
#include "common/xfpm-config.h"
#include "common/xfpm-icons.h"
#include "common/xfpm-power-common.h"
#include "common/xfpm-brightness.h"
#include "common/xfpm-debug.h"
#ifdef XFPM_SYSTRAY
#include "src/xfpm-inhibit.h"
#endif
#include "power-manager-button.h"
Eric Koegel's avatar
Eric Koegel committed
#include "scalemenuitem.h"

#define SET_LEVEL_TIMEOUT (50)
#define PANEL_DEFAULT_ICON ("battery-full-charged")
#define PANEL_DEFAULT_ICON_SYMBOLIC ("battery-full-charged-symbolic")
#define PRESENTATION_MODE_ICON ("x-office-presentation-symbolic")
struct PowerManagerButtonPrivate
#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  XfcePanelPlugin *plugin;
  GDBusProxy      *inhibit_proxy;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  XfpmInhibit     *inhibit;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  XfconfChannel   *channel;

  UpClient        *upower;

  /* A list of BatteryDevices  */
  GList           *devices;

  /* The left-click popup menu, if one is being displayed */
  GtkWidget       *menu;

  /* The actual panel icon image */
  GtkWidget       *panel_icon_image;
  GtkWidget       *panel_presentation_mode;
  GtkWidget       *panel_label;
  GtkWidget       *hbox;
  /* Keep track of icon name to redisplay during size changes */
  gchar           *panel_icon_name;
  gchar           *panel_fallback_icon_name;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Keep track of the last icon size for use during updates */
  gint             panel_icon_width;
  /* Keep track of the tooltip */
  gchar           *tooltip;

  /* Upower 0.99 has a display device that can be used for the
   * panel image and tooltip description */
  UpDevice        *display_device;

  XfpmBrightness  *brightness;

  /* display brightness slider widget */
  GtkWidget       *range;
  /* Some laptops (and mostly newer ones with intel graphics) can turn off the
   * backlight completely. If the user is not careful and sets the brightness
   * very low using the slider, he might not be able to see the screen contents
   * anymore. Brightness keys do not work on every laptop, so it's better to use
   * a safe default minimum level that the user can change via the settings
   * editor if desired.
   */
  gint32           brightness_min_level;

  gint             show_panel_label;
  gboolean         presentation_mode;
  gboolean         show_presentation_indicator;

  /* filter range value changed events for snappier UI feedback */
  guint            set_level_timeout;
typedef struct
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GdkPixbuf   *pix;               /* Icon */
  GtkWidget   *img;               /* Icon image in the menu */
  gchar       *details;           /* Description of the device + state */
  gchar       *object_path;       /* UpDevice object path */
  UpDevice    *device;            /* Pointer to the UpDevice */
  gulong       changed_signal_id; /* device changed callback id */
  gulong       expose_signal_id;  /* expose-event callback id */
  GtkWidget   *menu_item;         /* The device's item on the menu (if shown) */
} BatteryDevice;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PROP_0 = 0,
  PROP_BRIGHTNESS_MIN_LEVEL,
  PROP_SHOW_PANEL_LABEL,
  PROP_PRESENTATION_MODE,
  PROP_SHOW_PRESENTATION_INDICATOR,
} POWER_MANAGER_BUTTON_PROPERTIES;

Simon Steinbeiss's avatar
Simon Steinbeiss committed
  SIG_ICON_NAME_CHANGED = 0,
  SIG_TOOLTIP_CHANGED,
  SIG_N_SIGNALS,
};

static guint __signals[SIG_N_SIGNALS] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (PowerManagerButton, power_manager_button, GTK_TYPE_TOGGLE_BUTTON)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
static void       power_manager_button_finalize                         (GObject *object);
static GList*     find_device_in_list                                   (PowerManagerButton *button,
                                                                         const gchar *object_path);
static gboolean   power_manager_button_device_icon_draw                 (GtkWidget *img,
                                                                         cairo_t *cr,
                                                                         gpointer userdata);
static void       power_manager_button_set_icon                         (PowerManagerButton *button);
static void       power_manager_button_set_label                        (PowerManagerButton *button,
                                                                         gdouble percentage,
                                                                         guint64 time_to_empty_or_full);
#ifdef XFCE_PLUGIN
static void       power_manager_button_toggle_presentation_mode         (GtkMenuItem *mi,
                                                                         GtkSwitch *sw);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
static void       power_manager_button_update_presentation_indicator    (PowerManagerButton *button);
#endif
Simon Steinbeiss's avatar
Simon Steinbeiss committed
static void       power_manager_button_update_label                     (PowerManagerButton *button,
                                                                         UpDevice *device);
static gboolean   power_manager_button_press_event                      (GtkWidget *widget,
                                                                         GdkEventButton *event);
static gboolean   power_manager_button_menu_add_device                  (PowerManagerButton *button,
                                                                         BatteryDevice *battery_device,
                                                                         gboolean append);
static void       increase_brightness                                   (PowerManagerButton *button);
static void       decrease_brightness                                   (PowerManagerButton *button);
static void       battery_device_remove_pix                             (BatteryDevice *battery_device);
Eric Koegel's avatar
Eric Koegel committed
static BatteryDevice*
get_display_device (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GList *item = NULL;
  gdouble highest_percentage = 0;
  BatteryDevice *display_device = NULL;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_return_val_if_fail (POWER_MANAGER_IS_BUTTON(button), NULL);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (button->priv->display_device)
  {
    item = find_device_in_list (button, up_device_get_object_path (button->priv->display_device));
    if (item)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      return item->data;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* We want to find the battery or ups device with the highest percentage
   * and use that to get our tooltip from */
  for (item = g_list_first (button->priv->devices); item != NULL; item = g_list_next (item))
  {
    BatteryDevice *battery_device = item->data;
    guint type = 0;
    gdouble percentage;

    if (!battery_device->device || !UP_IS_DEVICE(battery_device->device))
    {
Loading
Loading full blame...