I'm not sure what the context here is (Are these boxes moving or stationary? Are you looking for a physically accurate resolution, or simply a geometrically correct one?), but it seems like you could accomplish this in the following way:
1) Determine if there is a box collision
2) Determine the intersection of the two boxes, which would produce a third box. The width and height of the box is your penetration depth.
3) move the center of one of the boxes by the penetration depth, (x - width, y - height).
This should cause the boxes to become disjoint.
FYI: Intersection of two boxes can be computed by taking the max of the mins and the mins of the maxes from both boxes.
Here is some code from my engine for box intersection:
bool Bounds::IntersectsBounds(const Bounds &other) const
{
return !(min.x > other.max.x || max.x < other.min.x
|| min.y > other.max.y || max.y < other.min.y);
}
bool Bounds::Intersection(const Bounds &other, Bounds &outBounds) const
{
if (!this->IntersectsBounds(other)) {
return false;
}
outBounds.min.x = std::max(min.x, other.min.x);
outBounds.min.y = std::max(min.y, other.min.y);
outBounds.max.x = std::min(max.x, other.max.x);
outBounds.max.y = std::min(max.y, other.max.y);
return true;
}
In this case, the "outBounds" variable is the intersection of the two boxes (which in this case is your penetration depth). You can use the width/height of this box to perform your collision resolution.