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 gboolean gdl_dock_dock_request (GdlDockObject *object, gint x, gint y, GdlDockRequest *request) { GdlDock *dock; guint bw; gint rel_x, rel_y; GtkAllocation *alloc; gboolean may_dock = FALSE; GdlDockRequest my_request; g_return_val_if_fail (GDL_IS_DOCK (object), FALSE); /* we get (x,y) in our allocation coordinates system */ dock = GDL_DOCK (object); /* Get dock size. */ alloc = &(GTK_WIDGET (dock)->allocation); bw = GTK_CONTAINER (dock)->border_width; /* Get coordinates relative to our allocation area. */ rel_x = x - alloc->x; rel_y = y - alloc->y; if (request) my_request = *request; /* Check if coordinates are in GdlDock widget. */ if (rel_x > 0 && rel_x < alloc->width && rel_y > 0 && rel_y < alloc->height) { /* It's inside our area. */ may_dock = TRUE; /* Set docking indicator rectangle to the GdlDock size. */ my_request.rect.x = alloc->x + bw; my_request.rect.y = alloc->y + bw; my_request.rect.width = alloc->width - 2*bw; my_request.rect.height = alloc->height - 2*bw; /* If GdlDock has no root item yet, set the dock itself as possible target. */ if (!dock->root) { my_request.position = GDL_DOCK_TOP; my_request.target = object; } else { my_request.target = dock->root; /* See if it's in the border_width band. */ if (rel_x < bw) { my_request.position = GDL_DOCK_LEFT; my_request.rect.width *= SPLIT_RATIO; } else if (rel_x > alloc->width - bw) { my_request.position = GDL_DOCK_RIGHT; my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO); my_request.rect.width *= SPLIT_RATIO; } else if (rel_y < bw) { my_request.position = GDL_DOCK_TOP; my_request.rect.height *= SPLIT_RATIO; } else if (rel_y > alloc->height - bw) { my_request.position = GDL_DOCK_BOTTOM; my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO); my_request.rect.height *= SPLIT_RATIO; } else { /* Otherwise try our children. */ /* give them allocation coordinates (we are a GTK_NO_WINDOW) widget */ may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock->root), x, y, &my_request); } } } if (may_dock && request) *request = my_request; return may_dock; }