static void gdl_dock_master_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GdlDockMaster *master = GDL_DOCK_MASTER (object); switch (prop_id) { case PROP_DEFAULT_TITLE: g_free (master->_priv->default_title); master->_priv->default_title = g_value_dup_string (value); break; case PROP_LOCKED: if (g_value_get_int (value) >= 0) gdl_dock_master_lock_unlock (master, (g_value_get_int (value) > 0)); break; case PROP_SWITCHER_STYLE: gdl_dock_master_set_switcher_style (master, g_value_get_enum (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gdl_dock_set_title (GdlDock *dock) { GdlDockObject *object = GDL_DOCK_OBJECT (dock); gchar *title = NULL; gboolean free_title = FALSE; if (!dock->_priv->window) return; if (!dock->_priv->auto_title && object->long_name) { title = object->long_name; } else if (object->master) { g_object_get (object->master, "default-title", &title, NULL); free_title = TRUE; } if (!title && dock->root) { g_object_get (dock->root, "long-name", &title, NULL); free_title = TRUE; } if (!title) { /* set a default title in the long_name */ dock->_priv->auto_title = TRUE; free_title = FALSE; title = object->long_name = g_strdup_printf ( _("Dock #%d"), GDL_DOCK_MASTER (object->master)->dock_number++); } gtk_window_set_title (GTK_WINDOW (dock->_priv->window), title); if (free_title) g_free (title); }
static void gdl_dock_set_title (GdlDock *dock) { GdlDockObject *object = GDL_DOCK_OBJECT (dock); gchar *title = NULL; if (!dock->priv->window) return; if (!dock->priv->auto_title && gdl_dock_object_get_long_name (object)) { title = g_strdup (gdl_dock_object_get_long_name (object)); } else if (gdl_dock_object_get_master (object) != NULL) { g_object_get (G_OBJECT (gdl_dock_object_get_master (object)), "default-title", &title, NULL); } if (!title && dock->priv->root) { g_object_get (dock->priv->root, "long-name", &title, NULL); } if (!title) { /* set a default title in the long_name */ dock->priv->auto_title = TRUE; title = gdl_dock_master_get_dock_name (GDL_DOCK_MASTER (gdl_dock_object_get_master (object))); } gtk_window_set_title (GTK_WINDOW (dock->priv->window), title); g_free (title); }
static void gdl_dock_master_drag_begin (GdlDockItem *item, gpointer data) { GdlDockMaster *master; GdlDockRequest *request; g_return_if_fail (data != NULL); g_return_if_fail (item != NULL); master = GDL_DOCK_MASTER (data); if (!master->_priv->drag_request) master->_priv->drag_request = g_new0 (GdlDockRequest, 1); request = master->_priv->drag_request; /* Set the target to itself so it won't go floating with just a click. */ request->applicant = GDL_DOCK_OBJECT (item); request->target = GDL_DOCK_OBJECT (item); request->position = GDL_DOCK_FLOATING; if (G_IS_VALUE (&request->extra)) g_value_unset (&request->extra); master->_priv->rect_drawn = FALSE; master->_priv->rect_owner = NULL; }
static void gdl_dock_master_drag_end (GdlDockItem *item, gboolean cancelled, gpointer data) { GdlDockMaster *master; GdlDockRequest *request; g_return_if_fail (data != NULL); g_return_if_fail (item != NULL); master = GDL_DOCK_MASTER (data); request = master->_priv->drag_request; g_return_if_fail (GDL_DOCK_OBJECT (item) == request->applicant); /* Erase previously drawn rectangle */ if (master->_priv->rect_drawn) gdl_dock_master_xor_rect (master); /* cancel conditions */ if (cancelled || request->applicant == request->target) return; /* dock object to the requested position */ gdl_dock_object_dock (request->target, request->applicant, request->position, &request->extra); g_signal_emit (master, master_signals [LAYOUT_CHANGED], 0); }
/** * gdl_dock_object_get_controller: * @object: a #GdlDockObject * * Retrieves the controller of the object. * * Return value: (transfer none): a #GdlDockObject object * * Since: 3.6 */ GdlDockObject * gdl_dock_object_get_controller (GdlDockObject *object) { g_return_val_if_fail (GDL_IS_DOCK_OBJECT (object), NULL); return gdl_dock_master_get_controller (GDL_DOCK_MASTER (object->priv->master)); }
/** * gdl_dock_object_bind: * @object: A #GdlDockObject * @master: A #GdlDockMaster * * Add a link between a #GdlDockObject and a master. It is normally not used * directly because it is automatically called when a new object is docked. */ void gdl_dock_object_bind (GdlDockObject *object, GObject *master) { g_return_if_fail (object != NULL && master != NULL); g_return_if_fail (GDL_IS_DOCK_MASTER (master)); if (object->priv->master == master) /* nothing to do here */ return; if (object->priv->master) { g_warning (_("Attempt to bind to %p an already bound dock object %p " "(current master: %p)"), master, object, object->priv->master); return; } gdl_dock_master_add (GDL_DOCK_MASTER (master), object); object->priv->master = master; #ifndef GDL_DISABLE_DEPRECATED object->deprecated_master = master; #endif g_object_add_weak_pointer (master, (gpointer *) &object->priv->master); g_object_notify (G_OBJECT (object), "master"); }
/** * gdl_dock_add_item: * @dock: A #GdlDock widget * @item: A #GdlDockItem widget * @placement: A position for the widget * * Dock in @dock, the widget @item at the position defined by @placement. The * function takes care of finding the right parent widget eventually creating * it if needed. */ void gdl_dock_add_item (GdlDock *dock, GdlDockItem *item, GdlDockPlacement placement) { GdlDockObject *placeholder; GdlDockObject *parent = NULL; GdlDockPlacement place; g_return_if_fail (dock != NULL); g_return_if_fail (item != NULL); /* Check if a placeholder widget already exist in the same dock */ placeholder = gdl_dock_master_get_object (GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))), gdl_dock_object_get_name (GDL_DOCK_OBJECT (item))); if ((placeholder != GDL_DOCK_OBJECT (item)) && (placeholder != NULL)) { if (gdl_dock_object_get_toplevel (placeholder) == dock) { parent = gdl_dock_object_get_parent_object (placeholder); } else { gtk_widget_destroy (GTK_WIDGET (placeholder)); } } if (parent && gdl_dock_object_child_placement (parent, placeholder, &place)) { gdl_dock_object_freeze (GDL_DOCK_OBJECT (parent)); gtk_widget_destroy (GTK_WIDGET (placeholder)); gdl_dock_object_dock (GDL_DOCK_OBJECT (parent), GDL_DOCK_OBJECT (item), place, NULL); gdl_dock_object_thaw (GDL_DOCK_OBJECT (parent)); } else if (placement == GDL_DOCK_FLOATING) /* Add the item to a new floating dock */ gdl_dock_add_floating_item (dock, item, 0, 0, -1, -1); else { GdlDockItem *best_dock_item; /* Non-floating item. */ if (dock->priv->root) { GdlDockPlacement local_placement; GtkRequisition preferred_size; best_dock_item = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (dock->priv->root), placement, 0); local_placement = gdl_dock_refine_placement (dock, best_dock_item, placement); gdl_dock_object_dock (GDL_DOCK_OBJECT (best_dock_item), GDL_DOCK_OBJECT (item), local_placement, NULL); } else { gdl_dock_object_dock (GDL_DOCK_OBJECT (dock), GDL_DOCK_OBJECT (item), placement, NULL); } } }
static void gdl_dock_master_dispose (GObject *g_object) { GdlDockMaster *master; g_return_if_fail (GDL_IS_DOCK_MASTER (g_object)); master = GDL_DOCK_MASTER (g_object); if (master->toplevel_docks) { g_list_foreach (master->toplevel_docks, (GFunc) gdl_dock_object_unbind, NULL); g_list_free (master->toplevel_docks); master->toplevel_docks = NULL; } if (master->dock_objects) { GSList *alive_docks = NULL; g_hash_table_foreach (master->dock_objects, (GHFunc) ht_foreach_build_slist, &alive_docks); while (alive_docks) { gdl_dock_object_unbind (GDL_DOCK_OBJECT (alive_docks->data)); alive_docks = g_slist_delete_link (alive_docks, alive_docks); } g_hash_table_destroy (master->dock_objects); master->dock_objects = NULL; } if (master->_priv) { if (master->_priv->idle_layout_changed_id) g_source_remove (master->_priv->idle_layout_changed_id); if (master->_priv->root_xor_gc) { g_object_unref (master->_priv->root_xor_gc); master->_priv->root_xor_gc = NULL; } if (master->_priv->drag_request) { if (G_IS_VALUE (&master->_priv->drag_request->extra)) g_value_unset (&master->_priv->drag_request->extra); g_free (master->_priv->drag_request); master->_priv->drag_request = NULL; } g_free (master->_priv->default_title); master->_priv->default_title = NULL; g_hash_table_destroy (master->_priv->locked_items); master->_priv->locked_items = NULL; g_hash_table_destroy (master->_priv->unlocked_items); master->_priv->unlocked_items = NULL; g_free (master->_priv); master->_priv = NULL; } GDL_CALL_PARENT (G_OBJECT_CLASS, dispose, (g_object)); }
/** * gdl_dock_get_named_items: * @dock: A #GdlDock widget * * Returns a list of all item bound to the master of the dock, not only * the children of this particular dock widget. * * Returns: (element-type GdlDockObject) (transfer container): A list of #GdlDockItem. The list should be freedwith g_list_free(), * but the item still belong to the master. */ GList * gdl_dock_get_named_items (GdlDock *dock) { GList *list = NULL; g_return_val_if_fail (dock != NULL, NULL); gdl_dock_master_foreach (GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))), (GFunc) _gdl_dock_foreach_build_list, &list); return list; }
/** * gdl_dock_get_item_by_name: * @dock: A #GdlDock widget * @name: An item name * * Looks for an #GdlDockItem widget bound to the master of the dock item. It * does not search only in the children of this particular dock widget. * * Returns: (transfer none): A #GdlDockItem widget or %NULL */ GdlDockItem * gdl_dock_get_item_by_name (GdlDock *dock, const gchar *name) { GdlDockObject *found; g_return_val_if_fail (dock != NULL && name != NULL, NULL); /* proxy the call to our master */ found = gdl_dock_master_get_object (GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))), name); return (found && GDL_IS_DOCK_ITEM (found)) ? GDL_DOCK_ITEM (found) : NULL; }
void gdl_dock_object_unbind (GdlDockObject *object) { g_return_if_fail (object != NULL); g_object_ref (object); /* detach the object first */ if (GDL_DOCK_OBJECT_ATTACHED (object)) gdl_dock_object_detach (object, TRUE); if (object->master) { GObject *master = object->master; g_object_remove_weak_pointer (master, (gpointer *) &object->master); object->master = NULL; gdl_dock_master_remove (GDL_DOCK_MASTER (master), object); g_object_notify (G_OBJECT (object), "master"); } g_object_unref (object); }
static void gdl_dock_hide (GtkWidget *widget) { GdlDock *dock; GdlDockMaster *master; g_return_if_fail (widget != NULL); g_return_if_fail (GDL_IS_DOCK (widget)); GTK_WIDGET_CLASS (gdl_dock_parent_class)->hide (widget); dock = GDL_DOCK (widget); if (dock->priv->floating && dock->priv->window) gtk_widget_hide (dock->priv->window); master = GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))); if (GDL_DOCK (gdl_dock_master_get_controller (master)) == dock) { gdl_dock_master_foreach_toplevel (master, FALSE, (GFunc) gdl_dock_foreach_automatic, gtk_widget_hide); } }
/** * gdl_dock_object_unbind: * @object: A #GdlDockObject * * This removes the link between an dock object and its master. */ void gdl_dock_object_unbind (GdlDockObject *object) { g_return_if_fail (object != NULL); g_object_ref (object); /* detach the object first */ gdl_dock_object_detach (object, TRUE); if (object->priv->master) { GObject *master = object->priv->master; g_object_remove_weak_pointer (master, (gpointer *) &object->priv->master); object->priv->master = NULL; #ifndef GDL_DISABLE_DEPRECATED object->deprecated_master = NULL; #endif gdl_dock_master_remove (GDL_DOCK_MASTER (master), object); g_object_notify (G_OBJECT (object), "master"); } g_object_unref (object); }
static void gdl_dock_master_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GdlDockMaster *master = GDL_DOCK_MASTER (object); switch (prop_id) { case PROP_DEFAULT_TITLE: g_value_set_string (value, master->_priv->default_title); break; case PROP_LOCKED: g_value_set_int (value, COMPUTE_LOCKED (master)); break; case PROP_SWITCHER_STYLE: g_value_set_enum (value, master->_priv->switcher_style); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gdl_dock_master_drag_motion (GdlDockItem *item, gint root_x, gint root_y, gpointer data) { GdlDockMaster *master; GdlDockRequest my_request, *request; GdkWindow *window; gint win_x, win_y; gint x, y; GdlDock *dock = NULL; gboolean may_dock = FALSE; g_return_if_fail (item != NULL && data != NULL); master = GDL_DOCK_MASTER (data); request = master->_priv->drag_request; g_return_if_fail (GDL_DOCK_OBJECT (item) == request->applicant); my_request = *request; /* first look under the pointer */ window = gdk_window_at_pointer (&win_x, &win_y); if (window) { GtkWidget *widget; /* ok, now get the widget who owns that window and see if we can get to a GdlDock by walking up the hierarchy */ gdk_window_get_user_data (window, (gpointer) &widget); if (GTK_IS_WIDGET (widget)) { while (widget && (!GDL_IS_DOCK (widget) || GDL_DOCK_OBJECT_GET_MASTER (widget) != master)) widget = widget->parent; if (widget) { gint win_w, win_h; /* verify that the pointer is still in that dock (the user could have moved it) */ gdk_window_get_geometry (widget->window, NULL, NULL, &win_w, &win_h, NULL); gdk_window_get_origin (widget->window, &win_x, &win_y); if (root_x >= win_x && root_x < win_x + win_w && root_y >= win_y && root_y < win_y + win_h) dock = GDL_DOCK (widget); } } } if (dock) { /* translate root coordinates into dock object coordinates (i.e. widget coordinates) */ gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y); x = root_x - win_x; y = root_y - win_y; may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock), x, y, &my_request); } else { GList *l; /* try to dock the item in all the docks in the ring in turn */ for (l = master->toplevel_docks; l; l = l->next) { dock = GDL_DOCK (l->data); /* translate root coordinates into dock object coordinates (i.e. widget coordinates) */ gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y); x = root_x - win_x; y = root_y - win_y; may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock), x, y, &my_request); if (may_dock) break; } } if (!may_dock) { GtkRequisition req; /* Special case for GdlDockItems : they must respect the flags */ if(GDL_IS_DOCK_ITEM(item) && GDL_DOCK_ITEM(item)->behavior & GDL_DOCK_ITEM_BEH_NEVER_FLOATING) return; dock = NULL; my_request.target = GDL_DOCK_OBJECT ( gdl_dock_object_get_toplevel (request->applicant)); my_request.position = GDL_DOCK_FLOATING; gdl_dock_item_preferred_size (GDL_DOCK_ITEM (request->applicant), &req); my_request.rect.width = req.width; my_request.rect.height = req.height; my_request.rect.x = root_x - GDL_DOCK_ITEM (request->applicant)->dragoff_x; my_request.rect.y = root_y - GDL_DOCK_ITEM (request->applicant)->dragoff_y; /* setup extra docking information */ if (G_IS_VALUE (&my_request.extra)) g_value_unset (&my_request.extra); g_value_init (&my_request.extra, GDK_TYPE_RECTANGLE); g_value_set_boxed (&my_request.extra, &my_request.rect); } /* if we want to enforce GDL_DOCK_ITEM_BEH_NEVER_FLOATING */ /* the item must remain attached to the controller, otherwise */ /* it could be inserted in another floating dock */ /* so check for the flag at this moment */ else if(GDL_IS_DOCK_ITEM(item) && GDL_DOCK_ITEM(item)->behavior & GDL_DOCK_ITEM_BEH_NEVER_FLOATING && dock != GDL_DOCK(master->controller)) return; if (!(my_request.rect.x == request->rect.x && my_request.rect.y == request->rect.y && my_request.rect.width == request->rect.width && my_request.rect.height == request->rect.height && dock == master->_priv->rect_owner)) { /* erase the previous rectangle */ if (master->_priv->rect_drawn) gdl_dock_master_xor_rect (master); } /* set the new values */ *request = my_request; master->_priv->rect_owner = dock; /* draw the previous rectangle */ if (~master->_priv->rect_drawn) gdl_dock_master_xor_rect (master); }
static GObject * gdl_dock_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_param) { GObject *g_object; g_object = G_OBJECT_CLASS (gdl_dock_parent_class)-> constructor (type, n_construct_properties, construct_param); if (g_object) { GdlDock *dock = GDL_DOCK (g_object); GdlDockMaster *master; /* create a master for the dock if none was provided in the construction */ master = GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))); if (!master) { gdl_dock_object_set_manual (GDL_DOCK_OBJECT (dock)); master = g_object_new (GDL_TYPE_DOCK_MASTER, NULL); /* the controller owns the master ref */ gdl_dock_object_bind (GDL_DOCK_OBJECT (dock), G_OBJECT (master)); } if (dock->priv->floating) { GdlDockObject *controller; /* create floating window for this dock */ dock->priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_object_set_data (G_OBJECT (dock->priv->window), "dock", dock); /* set position and default size */ gtk_window_set_position (GTK_WINDOW (dock->priv->window), GTK_WIN_POS_MOUSE); gtk_window_set_default_size (GTK_WINDOW (dock->priv->window), dock->priv->width, dock->priv->height); gtk_window_set_type_hint (GTK_WINDOW (dock->priv->window), GDK_WINDOW_TYPE_HINT_TOOLBAR); gdl_dock_set_skip_taskbar (dock, dock->priv->skip_taskbar); /* metacity ignores this */ gtk_window_move (GTK_WINDOW (dock->priv->window), dock->priv->float_x, dock->priv->float_y); /* connect to the configure event so we can track down window geometry */ g_signal_connect (dock->priv->window, "configure_event", (GCallback) gdl_dock_floating_configure_event_cb, dock); /* set the title and connect to the long_name notify queue so we can reset the title when this prop changes */ gdl_dock_set_title (dock); g_signal_connect (dock, "notify::long-name", (GCallback) gdl_dock_notify_cb, NULL); gtk_container_add (GTK_CONTAINER (dock->priv->window), GTK_WIDGET (dock)); g_signal_connect (dock->priv->window, "delete_event", G_CALLBACK (gdl_dock_floating_window_delete_event_cb), NULL); } } return g_object; }