#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>
#include <cstring>
#include <cstdlib>
using namespace std;

typedef pair<int,int> pii;
typedef vector<pii> vpii;
typedef vector<int> vint;

int h, w, kingx, kingy;
char fd[54][54];
vector<vpii> G;
vpii hole0;

int hdy[] = {-1, -1, 0, 1, 2, 2, 1, 0};
int hdx[] = {0, 1, 2, 2, 1, 0, -1, -1};
int kdy[] = {-1, 0, 1, 0};
int kdx[] = {0, 1, 0, -1};

const int INF = 1000000000;

inline int vindex(int y, int x, int i){
	return (y * w + x) * 4 + i;
}

void calccost(int hy, int hx, vector<vint> &tbl){
	tbl.assign(h + 2, vint(w + 2, INF));
	if(fd[hy][hx] != 1) return;

	queue<int> q;
	int t = 1;
	q.push(hy << 8 | hx);
	q.push(-1);
	tbl[hy][hx] = 0;

	while(q.size() > 1){
		if(q.front() == -1){
			q.push(-1);
			++t;
		}
		else{
			hy = q.front() >> 8;
			hx = q.front() & 0xff;
			for(int i = 0; i < 4; ++i){
				int ny = hy + kdy[i];
				int nx = hx + kdx[i];
				if(fd[ny][nx] == 1 && tbl[ny][nx] == INF){
					tbl[ny][nx] = t;
					q.push(ny << 8 | nx);
				}
			}
		}
		q.pop();
	}
}

inline void add_edge(int from, int to, int cost){
	G[from].push_back(pii(cost, to));
}

int solve(){
	if(kingy == 1 && kingx == 1) return 0;

	G.assign(h * w * 4, vpii());

	vector<vint> tbl[2];
	int ty[2], tx[2];

	//edge from init
	for(int k = 0; k < 2; ++k){
		int fy = hole0[k].first;
		int fx = hole0[k].second;
		calccost(fy, fx, tbl[k]);
	}

	for(int i = 0; i < 4; ++i){
		for(int k = 0; k < 2; ++k){
			ty[k] = kingy + hdy[i * 2 + k];
			tx[k] = kingx + hdx[i * 2 + k];
		}

		int minsum = INF;
		for(int k = 0; k < 2; ++k){
			int sum = tbl[0][ty[k]][tx[k]] + tbl[1][ty[1-k]][tx[1-k]];
			minsum = min(minsum, sum);
		}
		
		if(minsum != INF){
			add_edge(0, vindex(kingy, kingx, i), minsum);
		}
	}

	for(int y = 0; y < 2; ++y)
	for(int x = 0; x < 2; ++x){
		fd[kingy + y][kingx + x] = 1;
	}

	for(int y = 1; y < h; ++y){
		for(int x = 1; x < w; ++x){
			if(!fd[y][x] || !fd[y+1][x] || !fd[y][x+1] || !fd[y+1][x+1]){
				continue;
			}

			fd[y][x] = fd[y+1][x] = fd[y][x+1] = fd[y+1][x+1] = 2;
			for(int i = 0; i < 4; ++i){
				int idx = vindex(y, x, i);
				int nearidx = vindex(y + kdy[i], x + kdx[i], (i + 2) & 3);
				add_edge(idx, nearidx, 1);

				for(int k = 0; k < 2; ++k){
					int fy = y + hdy[i * 2 + k];
					int fx = x + hdx[i * 2 + k];
					calccost(fy, fx, tbl[k]);
				}

				for(int j = 0; j < 4; ++j){
					if(i == j) continue;

					for(int k = 0; k < 2; ++k){
						ty[k] = y + hdy[j * 2 + k];
						tx[k] = x + hdx[j * 2 + k];
					}

					int minsum = INF;
					for(int k = 0; k < 2; ++k){
						int sum =
							tbl[0][ty[k]][tx[k]] +
							tbl[1][ty[1-k]][tx[1-k]];
						minsum = min(minsum, sum);
					}

					if(minsum != INF){
						add_edge(idx, vindex(y, x, j), minsum);
					}
				}
			}

			fd[y][x] = fd[y+1][x] = fd[y][x+1] = fd[y+1][x+1] = 1;
		}
	}

	priority_queue<pii,vpii,greater<pii> > pq;
	pq.push( pii(0, 0) );
	vector<int> mindist(h * w * 4, INF);
	mindist[0] = 0;
	
	int lastv = vindex(1, 1, 0);
	while(!pq.empty()){
		int c = pq.top().first;
		int v = pq.top().second;
		pq.pop();

		if(mindist[v] != c){
			continue;
		}

		if(lastv <= v && v <= lastv + 3){
			return c;
		}

		for(int i = 0; i < G[v].size(); ++i){
			int nc = c + G[v][i].first;
			int nv = G[v][i].second;

			if(mindist[nv] > nc){
				mindist[nv] = nc;
				pq.push(pii(nc, nv));
			}
		}
	}
	return -1;
}

int main(){
	char buf[55];
	while(scanf("%d%d", &h, &w), h){
		memset(fd, 0, sizeof fd);
		kingx = kingy = -1;
		hole0.clear();

		for(int i = 1; i <= h; ++i){
			scanf(" %s", buf + 1);
			for(int j = 1; j <= w; ++j){
				if(buf[j] == 'o'){
					fd[i][j] = 1;
				}
				else if(buf[j] == 'X'){
					fd[i][j] = 9;
					if(kingx == -1){
						kingx = j;
						kingy = i;
					}
				}
				else if(buf[j] == '.'){
					fd[i][j] = 1;
					hole0.push_back( pii(i, j) );
				}
			}
		}

		printf("%d\n", solve());
	}
}

Measured memory_bytes: 1312