Skip to content
Snippets Groups Projects
power-manager-button.c 57.9 KiB
Newer Older
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  {
    button->priv->channel = xfconf_channel_get (XFPM_CHANNEL);
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_dbus_proxy_new (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
                    G_DBUS_PROXY_FLAGS_NONE,
                    NULL,
                    "org.freedesktop.PowerManagement",
                    "/org/freedesktop/PowerManagement/Inhibit",
                    "org.freedesktop.PowerManagement.Inhibit",
                    NULL,
                    inhibit_proxy_ready_cb,
                    button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->inhibit = xfpm_inhibit_new ();
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Sane defaults for the systray and panel icon */
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->panel_icon_name = g_strdup (PANEL_DEFAULT_ICON_SYMBOLIC);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->panel_icon_name = g_strdup (PANEL_DEFAULT_ICON);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->panel_icon_width = 24;

  /* Sane default Gtk style */
  css_provider = gtk_css_provider_new ();
  gtk_css_provider_load_from_data (css_provider,
                                   "#xfce4-power-manager-plugin {"
                                   "padding: 1px;"
                                   "border-width: 1px;}",
                                   -1, NULL);
  gtk_style_context_add_provider (GTK_STYLE_CONTEXT (gtk_widget_get_style_context (GTK_WIDGET (button))),
                                  GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
  /* Intercept scroll events */
  gtk_widget_add_events (GTK_WIDGET (button), GDK_SCROLL_MASK);

  g_signal_connect (button->priv->upower, "device-added", G_CALLBACK (device_added_cb), button);
  g_signal_connect (button->priv->upower, "device-removed", G_CALLBACK (device_removed_cb), button);
power_manager_button_finalize (GObject *object)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  DBG("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button = POWER_MANAGER_BUTTON (object);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_free(button->priv->panel_icon_name);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (button->priv->set_level_timeout)
  {
    g_source_remove(button->priv->set_level_timeout);
    button->priv->set_level_timeout = 0;
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_signal_handlers_disconnect_by_data (button->priv->upower, button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  power_manager_button_remove_all_devices (button);
#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_object_unref (button->priv->plugin);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  G_OBJECT_CLASS (power_manager_button_parent_class)->finalize (object);
#ifdef XFCE_PLUGIN
power_manager_button_new (XfcePanelPlugin *plugin)
#ifdef XFPM_SYSTRAY
power_manager_button_new (void)
#endif
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button = NULL;
  button = g_object_new (POWER_MANAGER_TYPE_BUTTON, NULL, NULL);

#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->plugin = XFCE_PANEL_PLUGIN (g_object_ref (plugin));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  xfconf_g_property_bind (button->priv->channel,
                          XFPM_PROPERTIES_PREFIX BRIGHTNESS_SLIDER_MIN_LEVEL, G_TYPE_INT,
                          G_OBJECT (button), BRIGHTNESS_SLIDER_MIN_LEVEL);
  xfconf_g_property_bind (button->priv->channel, XFPM_PROPERTIES_PREFIX SHOW_PANEL_LABEL, G_TYPE_INT,
                          G_OBJECT (button), SHOW_PANEL_LABEL);
  xfconf_g_property_bind (button->priv->channel, XFPM_PROPERTIES_PREFIX PRESENTATION_MODE, G_TYPE_BOOLEAN,
                          G_OBJECT (button), PRESENTATION_MODE);
  xfconf_g_property_bind (button->priv->channel, XFPM_PROPERTIES_PREFIX SHOW_PRESENTATION_INDICATOR, G_TYPE_BOOLEAN,
                          G_OBJECT (button), SHOW_PRESENTATION_INDICATOR);
  return GTK_WIDGET (button);
static gboolean
power_manager_button_press_event (GtkWidget *widget, GdkEventButton *event)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button = POWER_MANAGER_BUTTON (widget);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (event->button == 1 && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
  {
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
    power_manager_button_show_menu (button);
    return TRUE;
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (event->button == 2)
  {
    gboolean state;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    state = xfconf_channel_get_bool (button->priv->channel, XFPM_PROPERTIES_PREFIX PRESENTATION_MODE, FALSE);
    xfconf_channel_set_bool (button->priv->channel, XFPM_PROPERTIES_PREFIX PRESENTATION_MODE, !state);
    return TRUE;
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  return FALSE;
#ifdef XFCE_PLUGIN
power_manager_button_size_changed_cb (XfcePanelPlugin *plugin, gint size, PowerManagerButton *button)
#if !LIBXFCE4PANEL_CHECK_VERSION (4, 13, 0)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkStyleContext *context;
  GtkBorder padding, border;
  gint width;
  gint xthickness;
  gint ythickness;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_return_if_fail (POWER_MANAGER_IS_BUTTON (button));
  g_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
  g_return_if_fail (size > 0);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  size /= xfce_panel_plugin_get_nrows (plugin);
#if LIBXFCE4PANEL_CHECK_VERSION (4, 13, 0)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->panel_icon_width = xfce_panel_plugin_get_icon_size (plugin);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Calculate the size of the widget because the theme can override it */
  context = gtk_widget_get_style_context (GTK_WIDGET (button));
  gtk_style_context_get_padding (context, gtk_widget_get_state_flags (GTK_WIDGET (button)), &padding);
  gtk_style_context_get_border (context, gtk_widget_get_state_flags (GTK_WIDGET (button)), &border);
  xthickness = padding.left + padding.right + border.left + border.right;
  ythickness = padding.top + padding.bottom + border.top + border.bottom;

  /* Calculate the size of the space left for the icon */
  width = size - 2 * MAX (xthickness, ythickness);

  /* Since symbolic icons are usually only provided in 16px we
   * try to be clever and use size steps */
  if (width <= 21)
    button->priv->panel_icon_width = 16;
  else if (width >=22 && width <= 29)
    button->priv->panel_icon_width = 24;
  else if (width >= 30 && width <= 40)
    button->priv->panel_icon_width = 32;
  else
    button->priv->panel_icon_width = width;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* resize the plugin */
  gtk_widget_set_size_request (GTK_WIDGET (plugin), size, size);
  power_manager_button_set_icon (button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* resize the plugin button too */
  gtk_widget_set_size_request (GTK_WIDGET (button), -1, -1);
power_manager_button_style_update_cb (XfcePanelPlugin *plugin, PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_reset_style (GTK_WIDGET (plugin));
  power_manager_button_size_changed_cb (plugin, xfce_panel_plugin_get_size (plugin), button);
power_manager_button_free_data_cb (XfcePanelPlugin *plugin, PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_destroy (GTK_WIDGET (button));

static void
about_cb (GtkMenuItem *menuitem, gpointer user_data)
{
  xfpm_about ("xfce4-power-manager");
}
Eric Koegel's avatar
Eric Koegel committed
void
power_manager_button_show (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkWidget *mi;
  GtkWidget *hbox;
  GtkStyleContext *context;
  GtkCssProvider *css_provider;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_return_if_fail (POWER_MANAGER_IS_BUTTON (button));
#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  xfce_panel_plugin_add_action_widget (button->priv->plugin, GTK_WIDGET (button));
  xfce_panel_plugin_set_small (button->priv->plugin, TRUE);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->panel_icon_image = gtk_image_new ();
  button->priv->panel_presentation_mode = gtk_image_new_from_icon_name (PRESENTATION_MODE_ICON, GTK_ICON_SIZE_BUTTON);
  gtk_image_set_pixel_size (GTK_IMAGE (button->priv->panel_presentation_mode), button->priv->panel_icon_width);
  context = gtk_widget_get_style_context (button->priv->panel_presentation_mode);
  css_provider = gtk_css_provider_new ();
  gtk_css_provider_load_from_data (css_provider,
                                   ".presentation-mode { color: @warning_color; }",
                                   -1, NULL);
  gtk_style_context_add_provider (context,
                                  GTK_STYLE_PROVIDER (css_provider),
                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
  g_object_unref (css_provider);
  gtk_style_context_add_class (context, "presentation-mode");
  button->priv->panel_label = gtk_label_new ("");
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (button->priv->panel_presentation_mode), TRUE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (button->priv->panel_icon_image), TRUE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (button->priv->panel_label), TRUE, FALSE, 0);

  gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (hbox));

#ifdef XFCE_PLUGIN
  xfce_panel_plugin_menu_show_about (button->priv->plugin);
  g_signal_connect (button->priv->plugin, "about", G_CALLBACK (about_cb), NULL);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_signal_connect (button->priv->plugin, "size-changed",
                    G_CALLBACK (power_manager_button_size_changed_cb), button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_signal_connect (button->priv->plugin, "style-updated",
                    G_CALLBACK (power_manager_button_style_update_cb), button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_signal_connect (button->priv->plugin, "free-data",
                    G_CALLBACK (power_manager_button_free_data_cb), button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_show_all (GTK_WIDGET(button));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_set_visible (button->priv->panel_presentation_mode, button->priv->presentation_mode &&
                                                                 button->priv->show_presentation_indicator);
  power_manager_button_update_label (button, button->priv->display_device);
  power_manager_button_set_tooltip (button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Add all the devcies currently attached to the system */
  power_manager_button_add_all_devices (button);
static void
power_manager_button_update_presentation_indicator (PowerManagerButton *button)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_image_set_pixel_size (GTK_IMAGE (button->priv->panel_presentation_mode), button->priv->panel_icon_width);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_set_visible (button->priv->panel_presentation_mode, button->priv->presentation_mode &&
                                                                 button->priv->show_presentation_indicator);
static void
power_manager_button_update_label (PowerManagerButton *button, UpDevice *device)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  guint state;
  gdouble percentage;
  guint64 time_to_empty;
  guint64 time_to_full;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (!POWER_MANAGER_IS_BUTTON (button) || !UP_IS_DEVICE (device))
      return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (button->priv->show_panel_label <= 0 || button->priv->show_panel_label >3)
  {
    gtk_widget_hide (GTK_WIDGET (button->priv->panel_label));
    power_manager_button_size_changed_cb (button->priv->plugin,
                                          xfce_panel_plugin_get_size (button->priv->plugin),
                                          button);
    return;
  }
  else
    gtk_widget_show (GTK_WIDGET (button->priv->panel_label));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_object_get (device,
                "state", &state,
                "percentage", &percentage,
                "time-to-empty", &time_to_empty,
                "time-to-full", &time_to_full,
                NULL);

  /* Hide the label if the battery is fully charged,
   * if the state is unknown (no battery available)
     or if it's a desktop system */
  if (state == UP_DEVICE_STATE_CHARGING)
    power_manager_button_set_label (button, percentage, time_to_full);
  else if (state == UP_DEVICE_STATE_FULLY_CHARGED
           || state == UP_DEVICE_STATE_UNKNOWN
           || g_strcmp0 (button->priv->panel_icon_name, "ac-adapter-symbolic") == 0)
    gtk_widget_hide (GTK_WIDGET (button->priv->panel_label));
  else
    power_manager_button_set_label (button, percentage, time_to_empty);
menu_destroyed_cb(GtkMenuShell *menu, gpointer user_data)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button = POWER_MANAGER_BUTTON (user_data);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* menu destroyed, range slider is gone */
  button->priv->range = NULL;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* untoggle panel icon */
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), FALSE);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_menu_detach (GTK_MENU (button->priv->menu));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->menu = NULL;
}

static void
menu_item_destroyed_cb(GtkWidget *object, gpointer user_data)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button = POWER_MANAGER_BUTTON (user_data);
  GList *item;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  for (item = g_list_first (button->priv->devices); item != NULL; item = g_list_next (item))
  {
    BatteryDevice *battery_device = item->data;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    if (battery_device->menu_item == object)
    {
      battery_device->menu_item = NULL;
      return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
static void
menu_item_activate_cb(GtkWidget *object, gpointer user_data)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  PowerManagerButton *button = POWER_MANAGER_BUTTON (user_data);
  GList *item;

  for (item = g_list_first (button->priv->devices); item != NULL; item = g_list_next (item))
  {
    BatteryDevice *battery_device = item->data;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    if (battery_device->menu_item == object)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      /* Call xfpm settings with the device id */
      xfpm_preferences_device_id (battery_device->object_path);
      return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
static gboolean
power_manager_button_menu_add_device (PowerManagerButton *button, BatteryDevice *battery_device, gboolean append)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkWidget *mi, *label;
  guint type = 0;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_return_val_if_fail (POWER_MANAGER_IS_BUTTON (button), FALSE);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* We need a menu to attach it to */
  g_return_val_if_fail (button->priv->menu, FALSE);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (UP_IS_DEVICE (battery_device->device))
  {
    g_object_get (battery_device->device,
                  "kind", &type,
                  NULL);

    /* Don't add the display device or line power to the menu */
    if (type == UP_DEVICE_KIND_LINE_POWER || battery_device->device == button->priv->display_device)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      DBG("filtering device from menu (display or line power device)");
      return FALSE;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  mi = gtk_image_menu_item_new_with_label(battery_device->details);
G_GNUC_END_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Make the menu item be bold and multi-line */
  label = gtk_bin_get_child (GTK_BIN (mi));
  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
  /* add the image */
  battery_device->img = gtk_image_new_from_pixbuf (battery_device->pix);
  g_object_ref (battery_device->img);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), battery_device->img);
G_GNUC_END_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* keep track of the menu item in the battery_device so we can update it */
  battery_device->menu_item = mi;
  g_signal_connect(G_OBJECT (mi), "destroy", G_CALLBACK (menu_item_destroyed_cb), button);
  battery_device->expose_signal_id = g_signal_connect_after (G_OBJECT (battery_device->img),
                                                             "draw",
                                                             G_CALLBACK (power_manager_button_device_icon_draw),
                                                             battery_device->device);

  /* Active calls xfpm settings with the device's id to display details */
  g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menu_item_activate_cb), button);

  /* Add it to the menu */
  gtk_widget_show (mi);
  if (append)
    gtk_menu_shell_append (GTK_MENU_SHELL(button->priv->menu), mi);
  else
    gtk_menu_shell_prepend (GTK_MENU_SHELL(button->priv->menu), mi);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  return TRUE;
static void
add_inhibitor_to_menu (PowerManagerButton *button, const gchar *text)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkWidget *mi, *img;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Translators this is to display which app is inhibiting
   * power in the plugin menu. Example:
   * VLC is currently inhibiting power management
   */
  gchar *label = g_strdup_printf (_("%s is currently inhibiting power management"), text);

G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  mi = gtk_image_menu_item_new_with_label(label);
G_GNUC_END_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* add the image */
  img = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_MENU);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
G_GNUC_END_IGNORE_DEPRECATIONS

Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_set_can_focus (mi, FALSE);
  gtk_widget_show (mi);
  gtk_menu_shell_append (GTK_MENU_SHELL(button->priv->menu), mi);
  g_free (label);
static void
display_inhibitors (PowerManagerButton *button, GtkWidget *menu)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkWidget *separator_mi;
  gboolean needs_seperator = FALSE;

  g_return_if_fail (POWER_MANAGER_IS_BUTTON (button));
  g_return_if_fail (GTK_IS_MENU (menu));

  if (button->priv->inhibit_proxy)
  {
    GVariant *reply;
    GError   *error = NULL;

    reply = g_dbus_proxy_call_sync (button->priv->inhibit_proxy,
                                    "GetInhibitors",
                                    g_variant_new ("()"),
                                    G_DBUS_CALL_FLAGS_NONE,
                                    1000,
                                    NULL,
                                    &error);

    if (reply != NULL)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      GVariantIter *iter;
      gchar        *value;

      g_variant_get (reply, "(as)", &iter);

      if (g_variant_iter_n_children (iter) > 0)
      {
        needs_seperator = TRUE;
      }

      /* Add the list of programs to the menu */
      while (g_variant_iter_next (iter, "s", &value))
      {
        add_inhibitor_to_menu (button, value);
      }
      g_variant_iter_free (iter);
      g_variant_unref (reply);

    } else {
      g_warning ("failed calling GetInhibitors: %s", error->message);
      g_clear_error (&error);
    }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    if (needs_seperator)
    {
      /* add a separator */
      separator_mi = gtk_separator_menu_item_new ();
      gtk_widget_show (separator_mi);
      gtk_menu_shell_append (GTK_MENU_SHELL (menu), separator_mi);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
#else
static void
display_inhibitors (PowerManagerButton *button, GtkWidget *menu)
{
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  guint i;
  GtkWidget *separator_mi;
  const gchar **inhibitors;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  g_return_if_fail (POWER_MANAGER_IS_BUTTON (button));
  g_return_if_fail (GTK_IS_MENU (menu));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  inhibitors = xfpm_inhibit_get_inhibit_list (button->priv->inhibit);
  if (inhibitors != NULL && inhibitors[0] != NULL)
  {
    for (i=0; inhibitors[i] != NULL; i++)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      add_inhibitor_to_menu (button, inhibitors[i]);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    /* add a separator */
    separator_mi = gtk_separator_menu_item_new ();
    gtk_widget_show (separator_mi);
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), separator_mi);
  }

  g_free (inhibitors);
decrease_brightness (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gint32 level;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if ( !xfpm_brightness_has_hw (button->priv->brightness) )
    return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  xfpm_brightness_get_level (button->priv->brightness, &level);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if ( level > button->priv->brightness_min_level )
  {
    xfpm_brightness_down (button->priv->brightness, &level);
    if (button->priv->range)
      gtk_range_set_value (GTK_RANGE (button->priv->range), level);
  }
increase_brightness (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gint32 level, max_level;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (!xfpm_brightness_has_hw (button->priv->brightness))
    return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  max_level = xfpm_brightness_get_max_level (button->priv->brightness);
  xfpm_brightness_get_level (button->priv->brightness, &level);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (level < max_level)
  {
    xfpm_brightness_up (button->priv->brightness, &level);
    if (button->priv->range)
      gtk_range_set_value (GTK_RANGE (button->priv->range), level);
  }
brightness_set_level_with_timeout (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gint32 range_level, hw_level;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  range_level = (gint32) gtk_range_get_value (GTK_RANGE (button->priv->range));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  xfpm_brightness_get_level (button->priv->brightness, &hw_level);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (hw_level != range_level)
  {
    xfpm_brightness_set_level (button->priv->brightness, range_level);
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (button->priv->set_level_timeout)
  {
    g_source_remove(button->priv->set_level_timeout);
    button->priv->set_level_timeout = 0;
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  return FALSE;
range_value_changed_cb (PowerManagerButton *button, GtkWidget *widget)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (button->priv->set_level_timeout)
    return;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  button->priv->set_level_timeout =
    g_timeout_add (SET_LEVEL_TIMEOUT,
                   (GSourceFunc) brightness_set_level_with_timeout, button);
range_scroll_cb (GtkWidget *widget, GdkEvent *event, PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GdkEventScroll *scroll_event;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  scroll_event = (GdkEventScroll*)event;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (scroll_event->direction == GDK_SCROLL_UP)
    increase_brightness (button);
  else if (scroll_event->direction == GDK_SCROLL_DOWN)
    decrease_brightness (button);
range_show_cb (GtkWidget *widget, PowerManagerButton *button)
#if !GTK_CHECK_VERSION (3, 20, 0)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GdkDeviceManager* manager = gdk_display_get_device_manager (gdk_display_get_default());
  GdkDevice* pointer = gdk_device_manager_get_client_pointer (manager);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GdkSeat   *seat = gdk_display_get_default_seat (gdk_display_get_default());
  GdkDevice *pointer = gdk_seat_get_pointer (seat);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  TRACE("entering");
  /* Release these grabs as they will cause a lockup if pkexec is called
   * for the brightness helper */
  if (pointer)
  {
#if !GTK_CHECK_VERSION (3, 20, 0)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    gdk_seat_ungrab (seat);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_grab_remove (widget);
void
power_manager_button_toggle_presentation_mode (GtkMenuItem *mi, GtkSwitch *sw)
{
  g_return_if_fail (GTK_IS_SWITCH (sw));

  gtk_switch_set_active (sw, !gtk_switch_get_active (sw));
}


power_manager_button_show_menu (PowerManagerButton *button)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  GtkWidget *menu, *mi, *img = NULL;
  GtkWidget *box, *label, *sw;
  GdkScreen *gscreen;
  GList *item;
  gboolean show_separator_flag = FALSE;
  gint32 max_level, current_level = 0;

  TRACE("entering");

  g_return_if_fail (POWER_MANAGER_IS_BUTTON (button));

  if (gtk_widget_has_screen (GTK_WIDGET (button)))
      gscreen = gtk_widget_get_screen(GTK_WIDGET(button));
  else
      gscreen = gdk_display_get_default_screen(gdk_display_get_default());

  menu = gtk_menu_new ();
  gtk_menu_set_screen(GTK_MENU(menu), gscreen);
  /* keep track of the menu while it's being displayed */
  button->priv->menu = menu;
  g_signal_connect(GTK_MENU_SHELL(menu), "deactivate", G_CALLBACK(menu_destroyed_cb), button);
  gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (button), NULL);

  for (item = g_list_first (button->priv->devices); item != NULL; item = g_list_next (item))
  {
    BatteryDevice *battery_device = item->data;

    if (power_manager_button_menu_add_device (button, battery_device, TRUE))
Simon Steinbeiss's avatar
Simon Steinbeiss committed
      /* If we add an item to the menu, show the separator */
      show_separator_flag = TRUE;
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  if (show_separator_flag)
  {
    /* separator */
    mi = gtk_separator_menu_item_new ();
    gtk_widget_show (mi);
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
  }
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  /* Display brightness slider - show if there's hardware support for it */
  if ( xfpm_brightness_has_hw (button->priv->brightness) )
  {
    max_level = xfpm_brightness_get_max_level (button->priv->brightness);
    /* Setup brightness steps */
    guint brightness_step_count =
      xfconf_channel_get_uint (button->priv->channel,
                               XFPM_PROPERTIES_PREFIX BRIGHTNESS_STEP_COUNT,
                               10);
    gboolean brightness_exponential =
      xfconf_channel_get_bool (button->priv->channel,
                               XFPM_PROPERTIES_PREFIX BRIGHTNESS_EXPONENTIAL,
                               FALSE);
    xfpm_brightness_set_step_count (button->priv->brightness,
                                    brightness_step_count,
                                    brightness_exponential);

Simon Steinbeiss's avatar
Simon Steinbeiss committed
    mi = scale_menu_item_new_with_range (button->priv->brightness_min_level, max_level, 1);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    scale_menu_item_set_description_label (SCALE_MENU_ITEM (mi), _("<b>Display brightness</b>"));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    /* range slider */
    button->priv->range = scale_menu_item_get_scale (SCALE_MENU_ITEM (mi));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    /* update the slider to the current brightness level */
    xfpm_brightness_get_level (button->priv->brightness, &current_level);
    gtk_range_set_value (GTK_RANGE (button->priv->range), current_level);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    g_signal_connect_swapped (mi, "value-changed", G_CALLBACK (range_value_changed_cb), button);
    g_signal_connect (mi, "scroll-event", G_CALLBACK (range_scroll_cb), button);
    g_signal_connect (menu, "show", G_CALLBACK (range_show_cb), button);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    /* load and display the brightness icon and force it to 32px size */
    img = gtk_image_new_from_icon_name (XFPM_DISPLAY_BRIGHTNESS_ICON, GTK_ICON_SIZE_DND);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM(mi), img);
G_GNUC_END_IGNORE_DEPRECATIONS
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    gtk_image_set_pixel_size (GTK_IMAGE (img), 32);
    gtk_widget_show_all (mi);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
  }

  /* Presentation mode checkbox */
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  mi = gtk_menu_item_new ();
  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  label = gtk_label_new_with_mnemonic (_("Presentation _mode"));
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
  sw = gtk_switch_new ();
  gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (box), sw, FALSE, FALSE, 0);
  gtk_container_add (GTK_CONTAINER (mi), box);
  g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (power_manager_button_toggle_presentation_mode), sw);
  g_object_bind_property (G_OBJECT (button), PRESENTATION_MODE,
                          G_OBJECT (sw), "active",
                          G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
#else
  mi = gtk_check_menu_item_new_with_mnemonic (_("Presentation _mode"));
  gtk_widget_set_sensitive (mi, TRUE);
  xfconf_g_property_bind (button->priv->channel,
                          XFPM_PROPERTIES_PREFIX PRESENTATION_MODE,
                          G_TYPE_BOOLEAN, G_OBJECT (mi), "active");
#endif
  gtk_widget_show_all (mi);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
Simon Steinbeiss's avatar
Simon Steinbeiss committed

  /* Show any applications currently inhibiting now */
  display_inhibitors (button, menu);

  /* Power manager settings */
  mi = gtk_menu_item_new_with_mnemonic (_("_Settings..."));
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_widget_show (mi);
  gtk_menu_shell_append (GTK_MENU_SHELL(menu), mi);
  g_signal_connect (G_OBJECT(mi), "activate", G_CALLBACK(xfpm_preferences), NULL);
#if GTK_CHECK_VERSION (3, 22, 0)
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_menu_popup_at_widget (GTK_MENU (menu),
                            GTK_WIDGET (button),
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                            xfce_panel_plugin_get_orientation (button->priv->plugin) == GTK_ORIENTATION_VERTICAL
                            ? GDK_GRAVITY_WEST : GDK_GRAVITY_NORTH,
                            xfce_panel_plugin_get_orientation (button->priv->plugin) == GTK_ORIENTATION_VERTICAL
                            ? GDK_GRAVITY_EAST : GDK_GRAVITY_SOUTH,
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                            GDK_GRAVITY_NORTH,
                            GDK_GRAVITY_SOUTH,
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                            NULL);
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  gtk_menu_popup (GTK_MENU (menu),
                  NULL,
                  NULL,
#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                  xfce_panel_plugin_position_menu,
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                  NULL,
#ifdef XFCE_PLUGIN
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                  button->priv->plugin,
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                  NULL,
Simon Steinbeiss's avatar
Simon Steinbeiss committed
                  0,
                  gtk_get_current_event_time ());
Simon Steinbeiss's avatar
Simon Steinbeiss committed
  xfce_panel_plugin_register_menu (button->priv->plugin,
                                   GTK_MENU (menu));