summaryrefslogtreecommitdiff
path: root/mate-panel/panel-applet-frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-panel/panel-applet-frame.c')
-rw-r--r--mate-panel/panel-applet-frame.c1193
1 files changed, 1193 insertions, 0 deletions
diff --git a/mate-panel/panel-applet-frame.c b/mate-panel/panel-applet-frame.c
new file mode 100644
index 00000000..3610882e
--- /dev/null
+++ b/mate-panel/panel-applet-frame.c
@@ -0,0 +1,1193 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * panel-applet-frame.c: panel side container for applets
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <[email protected]>
+ * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Mark McLoughlin <[email protected]>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include "panel-applets-manager.h"
+#include "panel-profile.h"
+#include "panel.h"
+#include "applet.h"
+#include "panel-marshal.h"
+#include "panel-background.h"
+#include "panel-lockdown.h"
+#include "panel-stock-icons.h"
+#include "xstuff.h"
+#include "panel-schemas.h"
+
+#include "panel-applet-frame.h"
+
+#define PANEL_RESPONSE_DELETE 0
+#define PANEL_RESPONSE_DONT_RELOAD 1
+#define PANEL_RESPONSE_RELOAD 2
+
+static void mate_panel_applet_frame_activating_free (MatePanelAppletFrameActivating *frame_act);
+
+static void mate_panel_applet_frame_loading_failed (const char *iid,
+ PanelWidget *panel,
+ const char *id);
+
+static void mate_panel_applet_frame_load (const gchar *iid,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id);
+
+struct _MatePanelAppletFrameActivating {
+ gboolean locked;
+ PanelWidget *panel;
+ int position;
+ gboolean exactpos;
+ char *id;
+};
+
+/* MatePanelAppletFrame implementation */
+
+G_DEFINE_TYPE (MatePanelAppletFrame, mate_panel_applet_frame, GTK_TYPE_EVENT_BOX)
+
+#define MATE_PANEL_APPLET_FRAME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET_FRAME, MatePanelAppletFramePrivate))
+
+#define HANDLE_SIZE 10
+#define MATE_PANEL_APPLET_PREFS_PATH "/org/mate/panel/objects/%s/prefs/"
+
+struct _MatePanelAppletFramePrivate {
+ PanelWidget *panel;
+ AppletInfo *applet_info;
+
+ PanelOrientation orientation;
+
+ gchar *iid;
+
+ GtkAllocation child_allocation;
+ GdkRectangle handle_rect;
+
+ guint has_handle : 1;
+};
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static gboolean
+mate_panel_applet_frame_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ MatePanelAppletFrame *frame = MATE_PANEL_APPLET_FRAME (widget);
+ GtkStyleContext *context;
+ GtkStateFlags state;
+ cairo_pattern_t *bg_pattern;
+ PanelBackground *background;
+
+ if (GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->draw)
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->draw (widget, cr);
+
+ if (!frame->priv->has_handle)
+ return FALSE;
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, state);
+
+ cairo_save (cr);
+
+ /* Set the pattern transform so as to correctly render a patterned
+ * background with the handle */
+ gtk_style_context_get (context, state,
+ "background-image", &bg_pattern,
+ NULL);
+ background = &frame->priv->panel->background;
+
+ if (bg_pattern && (background->type == PANEL_BACK_IMAGE ||
+ (background->type == PANEL_BACK_COLOR && background->has_alpha))) {
+ cairo_matrix_t ptm;
+
+ cairo_matrix_init_translate (&ptm,
+ frame->priv->handle_rect.x,
+ frame->priv->handle_rect.y);
+ cairo_matrix_scale (&ptm,
+ frame->priv->handle_rect.width,
+ frame->priv->handle_rect.height);
+ cairo_pattern_set_matrix (bg_pattern, &ptm);
+ cairo_pattern_destroy (bg_pattern);
+ }
+
+ cairo_rectangle (cr,
+ frame->priv->handle_rect.x,
+ frame->priv->handle_rect.y,
+ frame->priv->handle_rect.width,
+ frame->priv->handle_rect.height);
+ cairo_clip (cr);
+ gtk_render_handle (context, cr,
+ 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ cairo_restore (cr);
+
+ gtk_style_context_restore (context);
+
+ return FALSE;
+}
+#else
+static void
+mate_panel_applet_frame_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ MatePanelAppletFrame *frame;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+
+ if (!frame->priv->has_handle)
+ return;
+
+ if (gtk_widget_is_drawable (widget)) {
+ GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ orientation = GTK_ORIENTATION_VERTICAL;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ orientation = GTK_ORIENTATION_HORIZONTAL;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_paint_handle (
+ gtk_widget_get_style (widget), gtk_widget_get_window (widget),
+ gtk_widget_get_state (widget),
+ GTK_SHADOW_OUT,
+ area, widget, "handlebox",
+ frame->priv->handle_rect.x,
+ frame->priv->handle_rect.y,
+ frame->priv->handle_rect.width,
+ frame->priv->handle_rect.height,
+ orientation);
+ }
+}
+
+static gboolean mate_panel_applet_frame_expose(GtkWidget* widget, GdkEventExpose* event)
+{
+ if (gtk_widget_is_drawable (widget))
+ {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->expose_event (widget, event);
+
+ mate_panel_applet_frame_paint (widget, &event->area);
+ }
+
+ return FALSE;
+}
+#endif
+
+static void
+mate_panel_applet_frame_update_background_size (MatePanelAppletFrame *frame,
+ GtkAllocation *old_allocation,
+ GtkAllocation *new_allocation)
+{
+ PanelBackground *background;
+
+ if (old_allocation->x == new_allocation->x &&
+ old_allocation->y == new_allocation->y &&
+ old_allocation->width == new_allocation->width &&
+ old_allocation->height == new_allocation->height)
+ return;
+
+ background = &frame->priv->panel->background;
+
+ if (background->type == PANEL_BACK_NONE ||
+ (background->type == PANEL_BACK_COLOR && !background->has_alpha))
+ return;
+
+ mate_panel_applet_frame_change_background (frame, background->type);
+}
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+mate_panel_applet_frame_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ guint border_width;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->get_preferred_width (widget, minimal_width, natural_width);
+ return;
+ }
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_get_preferred_width (child, minimal_width, natural_width);
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ *minimal_width += border_width;
+ *natural_width += border_width;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ *minimal_width += HANDLE_SIZE;
+ *natural_width += HANDLE_SIZE;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+mate_panel_applet_frame_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ guint border_width;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->get_preferred_height (widget, minimal_height, natural_height);
+ return;
+ }
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_get_preferred_height (child, minimal_height, natural_height);
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ *minimal_height += border_width;
+ *natural_height += border_width;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ *minimal_height += HANDLE_SIZE;
+ *natural_height += HANDLE_SIZE;
+ break;
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+#else
+static void
+mate_panel_applet_frame_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ GtkRequisition child_requisition;
+ guint border_width;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->size_request (widget, requisition);
+ return;
+ }
+
+ child = gtk_bin_get_child (bin);
+ if (child && gtk_widget_get_visible (child)) {
+ gtk_widget_size_request (child, &child_requisition);
+
+ requisition->width = child_requisition.width;
+ requisition->height = child_requisition.height;
+ }
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ requisition->width += border_width;
+ requisition->height += border_width;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ requisition->width += HANDLE_SIZE;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ requisition->height += HANDLE_SIZE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+#endif
+
+static void
+mate_panel_applet_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ MatePanelAppletFrame *frame;
+ GtkBin *bin;
+ GtkWidget *child;
+ GdkWindow *window;
+ GtkAllocation new_allocation;
+ GtkAllocation old_allocation;
+ GtkAllocation widget_allocation;
+
+ gtk_widget_get_allocation (widget, &widget_allocation);
+
+ old_allocation.x = widget_allocation.x;
+ old_allocation.y = widget_allocation.y;
+ old_allocation.width = widget_allocation.width;
+ old_allocation.height = widget_allocation.height;
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (!frame->priv->has_handle) {
+ GTK_WIDGET_CLASS (mate_panel_applet_frame_parent_class)->size_allocate (widget, allocation);
+ mate_panel_applet_frame_update_background_size (frame, &old_allocation, allocation);
+ return;
+ }
+
+ window = gtk_widget_get_window (widget);
+ child = gtk_bin_get_child (bin);
+ gtk_widget_set_allocation (widget, allocation);
+
+ frame->priv->handle_rect.x = 0;
+ frame->priv->handle_rect.y = 0;
+
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ frame->priv->handle_rect.width = HANDLE_SIZE;
+ frame->priv->handle_rect.height = allocation->height;
+
+ if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
+ GTK_TEXT_DIR_RTL) {
+ frame->priv->handle_rect.x = 0;
+ new_allocation.x = HANDLE_SIZE;
+ } else {
+ frame->priv->handle_rect.x = allocation->width - HANDLE_SIZE;
+ new_allocation.x = 0;
+ }
+
+ new_allocation.y = 0;
+ new_allocation.width = allocation->width - HANDLE_SIZE;
+ new_allocation.height = allocation->height;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ frame->priv->handle_rect.width = allocation->width;
+ frame->priv->handle_rect.height = HANDLE_SIZE;
+
+ new_allocation.x = 0;
+ new_allocation.y = HANDLE_SIZE;
+ new_allocation.width = allocation->width;
+ new_allocation.height = allocation->height - HANDLE_SIZE;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ new_allocation.width = MAX (1, new_allocation.width);
+ new_allocation.height = MAX (1, new_allocation.height);
+
+ /* If the child allocation changed, that means that the frame is drawn
+ * in a new place, so we must redraw the entire widget.
+ */
+ if (gtk_widget_get_mapped (widget) &&
+ (new_allocation.x != frame->priv->child_allocation.x ||
+ new_allocation.y != frame->priv->child_allocation.y ||
+ new_allocation.width != frame->priv->child_allocation.width ||
+ new_allocation.height != frame->priv->child_allocation.height))
+ gdk_window_invalidate_rect (window, &widget_allocation, FALSE);
+
+ if (gtk_widget_get_realized (widget)) {
+ guint border_width;
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ gdk_window_move_resize (window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ MAX (allocation->width - border_width * 2, 0),
+ MAX (allocation->height - border_width * 2, 0));
+ }
+
+ if (child && gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &new_allocation);
+
+ frame->priv->child_allocation = new_allocation;
+
+ mate_panel_applet_frame_update_background_size (frame,
+ &old_allocation,
+ allocation);
+}
+
+static inline gboolean
+button_event_in_rect (GdkEventButton *event,
+ GdkRectangle *rect)
+{
+ if (event->x >= rect->x &&
+ event->x <= (rect->x + rect->width) &&
+ event->y >= rect->y &&
+ event->y <= (rect->y + rect->height))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+mate_panel_applet_frame_button_changed (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ MatePanelAppletFrame *frame;
+ gboolean handled = FALSE;
+#if GTK_CHECK_VERSION (3, 0, 0)
+ GdkDisplay *display;
+ GdkDevice *pointer;
+ GdkDeviceManager *device_manager;
+#endif
+
+ frame = MATE_PANEL_APPLET_FRAME (widget);
+
+ if (!frame->priv->has_handle)
+ return handled;
+
+ if (event->window != gtk_widget_get_window (widget))
+ return FALSE;
+
+ switch (event->button) {
+ case 1:
+ case 2:
+ if (button_event_in_rect (event, &frame->priv->handle_rect)) {
+ if (event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS) {
+ panel_widget_applet_drag_start (
+ frame->priv->panel, GTK_WIDGET (frame),
+ PW_DRAG_OFF_CURSOR, event->time);
+ handled = TRUE;
+ } else if (event->type == GDK_BUTTON_RELEASE) {
+ panel_widget_applet_drag_end (frame->priv->panel);
+ handled = TRUE;
+ }
+ }
+ break;
+ case 3:
+ if (event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS) {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ display = gtk_widget_get_display (widget);
+ device_manager = gdk_display_get_device_manager (display);
+ pointer = gdk_device_manager_get_client_pointer (device_manager);
+ gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
+#endif
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->popup_menu (frame,
+ event->button,
+ event->time);
+
+ handled = TRUE;
+ } else if (event->type == GDK_BUTTON_RELEASE)
+ handled = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return handled;
+}
+
+static void
+mate_panel_applet_frame_finalize (GObject *object)
+{
+ MatePanelAppletFrame *frame = MATE_PANEL_APPLET_FRAME (object);
+
+ mate_panel_applets_manager_factory_deactivate (frame->priv->iid);
+
+ panel_lockdown_notify_remove (G_CALLBACK (mate_panel_applet_frame_sync_menu_state),
+ frame);
+
+ g_free (frame->priv->iid);
+ frame->priv->iid = NULL;
+
+ G_OBJECT_CLASS (mate_panel_applet_frame_parent_class)->finalize (object);
+}
+
+static void
+mate_panel_applet_frame_class_init (MatePanelAppletFrameClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+ gobject_class->finalize = mate_panel_applet_frame_finalize;
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ widget_class->draw = mate_panel_applet_frame_draw;
+ widget_class->get_preferred_width = mate_panel_applet_frame_get_preferred_width;
+ widget_class->get_preferred_height = mate_panel_applet_frame_get_preferred_height;
+#else
+ widget_class->expose_event = mate_panel_applet_frame_expose;
+ widget_class->size_request = mate_panel_applet_frame_size_request;
+#endif
+ widget_class->size_allocate = mate_panel_applet_frame_size_allocate;
+ widget_class->button_press_event = mate_panel_applet_frame_button_changed;
+ widget_class->button_release_event = mate_panel_applet_frame_button_changed;
+
+ g_type_class_add_private (klass, sizeof (MatePanelAppletFramePrivate));
+}
+
+static void
+mate_panel_applet_frame_init (MatePanelAppletFrame *frame)
+{
+ frame->priv = MATE_PANEL_APPLET_FRAME_GET_PRIVATE (frame);
+
+ frame->priv->panel = NULL;
+ frame->priv->orientation = PANEL_ORIENTATION_TOP;
+ frame->priv->applet_info = NULL;
+ frame->priv->has_handle = FALSE;
+}
+
+static void
+mate_panel_applet_frame_init_properties (MatePanelAppletFrame *frame)
+{
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->init_properties (frame);
+}
+
+void
+mate_panel_applet_frame_sync_menu_state (MatePanelAppletFrame *frame)
+{
+ PanelWidget *panel_widget;
+ gboolean locked_down;
+ gboolean locked;
+ gboolean lockable;
+ gboolean movable;
+ gboolean removable;
+
+ panel_widget = PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (frame)));
+
+ movable = mate_panel_applet_can_freely_move (frame->priv->applet_info);
+ removable = panel_profile_id_lists_are_writable ();
+ lockable = mate_panel_applet_lockable (frame->priv->applet_info);
+
+ locked = panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame));
+ locked_down = panel_lockdown_get_locked_down ();
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->sync_menu_state (frame, movable, removable, lockable, locked, locked_down);
+}
+
+void
+mate_panel_applet_frame_change_orientation (MatePanelAppletFrame *frame,
+ PanelOrientation orientation)
+{
+ if (orientation == frame->priv->orientation)
+ return;
+
+ frame->priv->orientation = orientation;
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_orientation (frame, orientation);
+}
+
+void
+mate_panel_applet_frame_change_size (MatePanelAppletFrame *frame,
+ guint size)
+{
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_size (frame, size);
+}
+
+void
+mate_panel_applet_frame_change_background (MatePanelAppletFrame *frame,
+ PanelBackgroundType type)
+{
+ GtkWidget *parent;
+
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (frame));
+
+ g_return_if_fail (PANEL_IS_WIDGET (parent));
+
+ if (frame->priv->has_handle) {
+ PanelBackground *background;
+
+ background = &PANEL_WIDGET (parent)->background;
+#if GTK_CHECK_VERSION (3, 0, 0)
+ panel_background_apply_css (background, GTK_WIDGET (frame));
+#else
+ panel_background_change_background_on_widget (background,
+ GTK_WIDGET (frame));
+#endif
+ }
+
+ MATE_PANEL_APPLET_FRAME_GET_CLASS (frame)->change_background (frame, type);
+}
+
+void
+mate_panel_applet_frame_set_panel (MatePanelAppletFrame *frame,
+ PanelWidget *panel)
+{
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+ frame->priv->panel = panel;
+}
+
+void
+_mate_panel_applet_frame_set_iid (MatePanelAppletFrame *frame,
+ const gchar *iid)
+{
+ if (frame->priv->iid)
+ g_free (frame->priv->iid);
+ frame->priv->iid = g_strdup (iid);
+}
+
+void
+_mate_panel_applet_frame_activated (MatePanelAppletFrame *frame,
+ MatePanelAppletFrameActivating *frame_act,
+ GError *error)
+{
+ AppletInfo *info;
+
+ g_assert (frame->priv->iid != NULL);
+
+ if (error != NULL) {
+ g_warning ("Failed to load applet %s:\n%s",
+ frame->priv->iid, error->message);
+ g_error_free (error);
+
+ mate_panel_applet_frame_loading_failed (frame->priv->iid,
+ frame_act->panel,
+ frame_act->id);
+ mate_panel_applet_frame_activating_free (frame_act);
+ gtk_widget_destroy (GTK_WIDGET (frame));
+
+ return;
+ }
+
+ frame->priv->panel = frame_act->panel;
+ gtk_widget_show_all (GTK_WIDGET (frame));
+
+ info = mate_panel_applet_register (GTK_WIDGET (frame), GTK_WIDGET (frame),
+ NULL, frame->priv->panel,
+ frame_act->locked, frame_act->position,
+ frame_act->exactpos, PANEL_OBJECT_APPLET,
+ frame_act->id);
+ frame->priv->applet_info = info;
+
+ panel_widget_set_applet_size_constrained (frame->priv->panel,
+ GTK_WIDGET (frame), TRUE);
+
+ mate_panel_applet_frame_sync_menu_state (frame);
+ mate_panel_applet_frame_init_properties (frame);
+
+ panel_lockdown_notify_add (G_CALLBACK (mate_panel_applet_frame_sync_menu_state),
+ frame);
+
+ mate_panel_applet_stop_loading (frame_act->id);
+ mate_panel_applet_frame_activating_free (frame_act);
+}
+
+void
+_mate_panel_applet_frame_update_flags (MatePanelAppletFrame *frame,
+ gboolean major,
+ gboolean minor,
+ gboolean has_handle)
+{
+ gboolean old_has_handle;
+
+ panel_widget_set_applet_expandable (
+ frame->priv->panel, GTK_WIDGET (frame), major, minor);
+
+ old_has_handle = frame->priv->has_handle;
+ frame->priv->has_handle = has_handle;
+
+ if (!old_has_handle && frame->priv->has_handle) {
+ /* we've added an handle, so we need to get the background for
+ * it */
+ PanelBackground *background;
+
+ background = &frame->priv->panel->background;
+ mate_panel_applet_frame_change_background (frame, background->type);
+ }
+}
+
+void
+_mate_panel_applet_frame_update_size_hints (MatePanelAppletFrame *frame,
+ gint *size_hints,
+ guint n_elements)
+{
+ if (frame->priv->has_handle) {
+ gint extra_size = HANDLE_SIZE + 1;
+ gint i;
+
+ for (i = 0; i < n_elements; i++)
+ size_hints[i] += extra_size;
+ }
+
+ /* It takes the ownership of size-hints array */
+ panel_widget_set_applet_size_hints (frame->priv->panel,
+ GTK_WIDGET (frame),
+ size_hints,
+ n_elements);
+}
+
+char *
+_mate_panel_applet_frame_get_background_string (MatePanelAppletFrame *frame,
+ PanelWidget *panel,
+ PanelBackgroundType type)
+{
+ GtkAllocation allocation;
+ int x;
+ int y;
+
+ gtk_widget_get_allocation (GTK_WIDGET (frame), &allocation);
+
+ x = allocation.x;
+ y = allocation.y;
+
+ if (frame->priv->has_handle) {
+ switch (frame->priv->orientation) {
+ case PANEL_ORIENTATION_TOP:
+ case PANEL_ORIENTATION_BOTTOM:
+ if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
+ GTK_TEXT_DIR_RTL)
+ x += frame->priv->handle_rect.width;
+ break;
+ case PANEL_ORIENTATION_LEFT:
+ case PANEL_ORIENTATION_RIGHT:
+ y += frame->priv->handle_rect.height;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ return panel_background_make_string (&panel->background, x, y);
+}
+
+static void
+mate_panel_applet_frame_reload_response (GtkWidget *dialog,
+ int response,
+ MatePanelAppletFrame *frame)
+{
+ AppletInfo *info;
+
+ g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+
+ if (!frame->priv->iid || !frame->priv->panel) {
+ g_object_unref (frame);
+ gtk_widget_destroy (dialog);
+ return;
+ }
+
+ info = frame->priv->applet_info;
+
+ if (response == PANEL_RESPONSE_RELOAD) {
+ PanelWidget *panel;
+ char *iid;
+ char *id = NULL;
+ int position = -1;
+ gboolean locked = FALSE;
+
+ panel = frame->priv->panel;
+ iid = g_strdup (frame->priv->iid);
+
+ if (info) {
+ id = g_strdup (info->id);
+ position = mate_panel_applet_get_position (info);
+ locked = panel_widget_get_applet_locked (panel, info->widget);
+ mate_panel_applet_clean (info);
+ }
+
+ mate_panel_applet_frame_load (iid, panel, locked,
+ position, TRUE, id);
+
+ g_free (iid);
+ g_free (id);
+
+ } else if (response == PANEL_RESPONSE_DELETE) {
+ /* if we can't write to applets list we can't really delete
+ it, so we'll just ignore this. FIXME: handle this
+ more correctly I suppose. */
+ if (panel_profile_id_lists_are_writable () && info)
+ panel_profile_delete_object (info);
+ }
+
+ g_object_unref (frame);
+ gtk_widget_destroy (dialog);
+}
+
+void
+_mate_panel_applet_frame_applet_broken (MatePanelAppletFrame *frame)
+{
+ GtkWidget *dialog;
+ GdkScreen *screen;
+ const char *applet_name = NULL;
+ char *dialog_txt;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (frame));
+
+ if (xstuff_is_display_dead ())
+ return;
+
+ if (frame->priv->iid) {
+ MatePanelAppletInfo *info;
+
+ info = (MatePanelAppletInfo *)mate_panel_applets_manager_get_applet_info (frame->priv->iid);
+ applet_name = mate_panel_applet_info_get_name (info);
+ }
+
+ if (applet_name)
+ dialog_txt = g_strdup_printf (_("\"%s\" has quit unexpectedly"), applet_name);
+ else
+ dialog_txt = g_strdup (_("Panel object has quit unexpectedly"));
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+ dialog_txt, applet_name ? applet_name : NULL);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you reload a panel object, it will automatically "
+ "be added back to the panel."));
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+
+ if (panel_profile_id_lists_are_writable ()) {
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("D_elete"), PANEL_RESPONSE_DELETE,
+ _("_Don't Reload"), PANEL_RESPONSE_DONT_RELOAD,
+ _("_Reload"), PANEL_RESPONSE_RELOAD,
+ NULL);
+ } else {
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Don't Reload"), PANEL_RESPONSE_DONT_RELOAD,
+ _("_Reload"), PANEL_RESPONSE_RELOAD,
+ NULL);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ PANEL_RESPONSE_RELOAD);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (mate_panel_applet_frame_reload_response),
+ g_object_ref (frame));
+
+ panel_widget_register_open_dialog (frame->priv->panel, dialog);
+ gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+ /* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+
+ gtk_widget_show (dialog);
+ g_free (dialog_txt);
+}
+
+void
+_mate_panel_applet_frame_applet_remove (MatePanelAppletFrame *frame)
+{
+ AppletInfo *info;
+
+ if (!frame->priv->applet_info)
+ return;
+
+ info = frame->priv->applet_info;
+ frame->priv->applet_info = NULL;
+
+ panel_profile_delete_object (info);
+}
+
+void
+_mate_panel_applet_frame_applet_move (MatePanelAppletFrame *frame)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkWidget *parent = gtk_widget_get_parent (widget);
+
+ if (!PANEL_IS_WIDGET (parent))
+ return;
+
+ panel_widget_applet_drag_start (PANEL_WIDGET (parent),
+ widget,
+ PW_DRAG_OFF_CENTER,
+ GDK_CURRENT_TIME);
+}
+
+void
+_mate_panel_applet_frame_applet_lock (MatePanelAppletFrame *frame,
+ gboolean locked)
+{
+ PanelWidget *panel_widget = PANEL_WIDGET (gtk_widget_get_parent (GTK_WIDGET (frame)));
+
+ if (panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame)) == locked)
+ return;
+
+ mate_panel_applet_toggle_locked (frame->priv->applet_info);
+}
+
+/* Generic methods */
+
+static GSList *no_reload_applets = NULL;
+
+enum {
+ LOADING_FAILED_RESPONSE_DONT_DELETE,
+ LOADING_FAILED_RESPONSE_DELETE
+};
+
+static void
+mate_panel_applet_frame_activating_free (MatePanelAppletFrameActivating *frame_act)
+{
+ g_free (frame_act->id);
+ g_slice_free (MatePanelAppletFrameActivating, frame_act);
+}
+
+GdkScreen *
+panel_applet_frame_activating_get_screen (MatePanelAppletFrameActivating *frame_act)
+{
+ return gtk_widget_get_screen (GTK_WIDGET(frame_act->panel));
+}
+
+PanelOrientation
+mate_panel_applet_frame_activating_get_orientation(MatePanelAppletFrameActivating *frame_act)
+{
+ return panel_widget_get_applet_orientation(frame_act->panel);
+}
+
+guint32
+mate_panel_applet_frame_activating_get_size (MatePanelAppletFrameActivating *frame_act)
+{
+ return frame_act->panel->sz;
+}
+
+gboolean
+mate_panel_applet_frame_activating_get_locked (MatePanelAppletFrameActivating *frame_act)
+{
+ return frame_act->locked;
+}
+
+gboolean
+mate_panel_applet_frame_activating_get_locked_down (MatePanelAppletFrameActivating *frame_act)
+{
+ return panel_lockdown_get_locked_down ();
+}
+
+gchar *
+mate_panel_applet_frame_activating_get_conf_path (MatePanelAppletFrameActivating *frame_act)
+{
+ return g_strdup_printf (MATE_PANEL_APPLET_PREFS_PATH, frame_act->id);
+}
+
+static void
+mate_panel_applet_frame_loading_failed_response (GtkWidget *dialog,
+ guint response,
+ char *id)
+{
+ gtk_widget_destroy (dialog);
+
+ if (response == LOADING_FAILED_RESPONSE_DELETE &&
+ !panel_lockdown_get_locked_down () &&
+ panel_profile_id_lists_are_writable ()) {
+ GSList *item;
+
+ item = g_slist_find_custom (no_reload_applets, id,
+ (GCompareFunc) strcmp);
+ if (item) {
+ g_free (item->data);
+ no_reload_applets = g_slist_delete_link (no_reload_applets,
+ item);
+ }
+
+ panel_profile_remove_from_list (PANEL_GSETTINGS_OBJECTS, id);
+ }
+
+ g_free (id);
+}
+
+static void
+mate_panel_applet_frame_loading_failed (const char *iid,
+ PanelWidget *panel,
+ const char *id)
+{
+ GtkWidget *dialog;
+ char *problem_txt;
+ gboolean locked_down;
+
+ no_reload_applets = g_slist_prepend (no_reload_applets,
+ g_strdup (id));
+
+ locked_down = panel_lockdown_get_locked_down ();
+
+ problem_txt = g_strdup_printf (_("The panel encountered a problem "
+ "while loading \"%s\"."),
+ iid);
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ locked_down ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "%s", problem_txt);
+ g_free (problem_txt);
+
+ if (locked_down) {
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_OK, LOADING_FAILED_RESPONSE_DONT_DELETE,
+ NULL);
+ } else {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Do you want to delete the applet "
+ "from your configuration?"));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ PANEL_STOCK_DONT_DELETE, LOADING_FAILED_RESPONSE_DONT_DELETE,
+ GTK_STOCK_DELETE, LOADING_FAILED_RESPONSE_DELETE,
+ NULL);
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ LOADING_FAILED_RESPONSE_DONT_DELETE);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_window_get_screen (GTK_WINDOW (panel->toplevel)));
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (mate_panel_applet_frame_loading_failed_response),
+ g_strdup (id));
+
+ panel_widget_register_open_dialog (panel, dialog);
+ gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+ /* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+
+ gtk_widget_show_all (dialog);
+
+ /* Note: this call will free the memory for id, so the variable should
+ * not get accessed afterwards. */
+ mate_panel_applet_stop_loading (id);
+}
+
+static void
+mate_panel_applet_frame_load (const gchar *iid,
+ PanelWidget *panel,
+ gboolean locked,
+ int position,
+ gboolean exactpos,
+ const char *id)
+{
+ MatePanelAppletFrameActivating *frame_act;
+
+ g_return_if_fail (iid != NULL);
+ g_return_if_fail (panel != NULL);
+ g_return_if_fail (id != NULL);
+
+ if (g_slist_find_custom (no_reload_applets, id,
+ (GCompareFunc) strcmp)) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ if (panel_lockdown_is_applet_disabled (iid)) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ frame_act = g_slice_new0 (MatePanelAppletFrameActivating);
+ frame_act->locked = locked;
+ frame_act->panel = panel;
+ frame_act->position = position;
+ frame_act->exactpos = exactpos;
+ frame_act->id = g_strdup (id);
+
+ if (!mate_panel_applets_manager_load_applet (iid, frame_act)) {
+ mate_panel_applet_frame_loading_failed (iid, panel, id);
+ mate_panel_applet_frame_activating_free (frame_act);
+ }
+}
+
+void
+mate_panel_applet_frame_load_from_gsettings (PanelWidget *panel_widget,
+ gboolean locked,
+ int position,
+ const char *id)
+{
+ GSettings *settings;
+ gchar *path;
+ gchar *applet_iid;
+
+ g_return_if_fail (panel_widget != NULL);
+ g_return_if_fail (id != NULL);
+
+ path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
+ settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
+ applet_iid = g_settings_get_string (settings, PANEL_OBJECT_APPLET_IID_KEY);
+ g_object_unref (settings);
+ g_free (path);
+
+ if (!applet_iid) {
+ mate_panel_applet_stop_loading (id);
+ return;
+ }
+
+ mate_panel_applet_frame_load (applet_iid, panel_widget,
+ locked, position, TRUE, id);
+
+ g_free (applet_iid);
+}
+
+void
+mate_panel_applet_frame_create (PanelToplevel *toplevel,
+ int position,
+ const char *iid)
+{
+ GSettings *settings;
+ gchar *path;
+ char *id;
+
+ g_return_if_fail (iid != NULL);
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position, FALSE);
+
+ path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
+ settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
+ g_settings_set_string (settings, PANEL_OBJECT_APPLET_IID_KEY, iid);
+
+ panel_profile_add_to_list (PANEL_GSETTINGS_OBJECTS, id);
+
+ g_free (id);
+ g_free (path);
+ g_object_unref (settings);
+}