diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c
index 0deeb80471b6ab54d32867908672385eb601f3bf..46ef814114376498ca72ccd61531082060490bb5 100644
--- a/src/conio/ciolib.c
+++ b/src/conio/ciolib.c
@@ -308,7 +308,6 @@ static int try_x_init(int mode)
 		cio_api.settitle=x_settitle;
 		cio_api.copytext=x_copytext;
 		cio_api.getcliptext=x_getcliptext;
-		cio_api.get_window_info=x_get_window_info;
 		cio_api.setscaling=x_setscaling;
 		cio_api.getscaling=x_getscaling;
 		cio_api.seticon=x_seticon;
diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c
index a62462046f26af25be375bb5a946f212d1add54f..d6302b08cca8a884dfce168db3e84ff876d4b137 100644
--- a/src/conio/x_cio.c
+++ b/src/conio/x_cio.c
@@ -182,22 +182,6 @@ char *x_getcliptext(void)
 	return(ret);
 }
 
-int x_get_window_info(int *width, int *height, int *xpos, int *ypos)
-{
-	pthread_mutex_lock(&vstatlock);
-	if(width)
-		*width=vstat.winwidth;
-	if(height)
-		*height=vstat.winheight;
-	pthread_mutex_unlock(&vstatlock);
-	if(xpos)
-		*xpos=x11_window_xpos;
-	if(ypos)
-		*ypos=x11_window_ypos;
-	
-	return(1);
-}
-
 /* Mouse event/keyboard thread */
 void x11_mouse_thread(void *data)
 {
diff --git a/src/conio/x_cio.h b/src/conio/x_cio.h
index 2a259d519a5fe1dfffad778523bd8b3979065608..095b5939c50301bece32c3b3e53c92467cafab37 100644
--- a/src/conio/x_cio.h
+++ b/src/conio/x_cio.h
@@ -74,7 +74,6 @@ char *x_getcliptext(void);
 int x_setfont(int font, int force);
 int x_getfont(void);
 int x_loadfont(const char *filename);
-int x_get_window_info(int *width, int *height, int *xpos, int *ypos);
 void x11_drawrect(struct rectlist *data);
 void x11_flush(void);
 void x_setscaling(double newval);
diff --git a/src/conio/x_events.c b/src/conio/x_events.c
index 9e133f63465126b617f20a2097ee083c73b9019e..7aec3da265b17bbc72ba637def1abdda6b3b80cb 100644
--- a/src/conio/x_events.c
+++ b/src/conio/x_events.c
@@ -33,7 +33,6 @@
 #include "x_cio.h"
 #include "utf8_codepages.h"
 
-static bool send_fullscreen(bool set);
 static void resize_window();
 
 /*
@@ -52,8 +51,6 @@ sem_t	pastebuf_set;
 sem_t	pastebuf_used;
 sem_t	init_complete;
 sem_t	mode_set;
-int x11_window_xpos;
-int x11_window_ypos;
 int x11_initialized=0;
 static sem_t	event_thread_complete;
 static int	terminate = 0;
@@ -180,7 +177,10 @@ static Window root;
 static char *wm_wm_name;
 static Atom copy_paste_selection = XA_PRIMARY;
 static bool map_pending = true;
-static int pending_width, pending_height, pending_xpos, pending_ypos;
+static int pending_width, pending_height;
+static int saved_xpos = -1, saved_ypos = -1;
+static int saved_width = -1, saved_height = -1;
+static double saved_scaling = 0.0;
 
 /* Array of Graphics Contexts */
 static GC gc;
@@ -567,6 +567,37 @@ fullscreen_geometry(int *x_org, int *y_org, int *width, int *height)
 	return true;
 }
 
+static bool
+get_frame_extents(int *l, int *r, int *t, int *b)
+{
+	long *extents;
+	unsigned char *prop;
+	unsigned long nir;
+	unsigned long bytes_left;
+	Atom atr;
+	int afr;
+	bool ret = false;
+
+	if (A(_NET_FRAME_EXTENTS) != None && win != 0) {
+		if (x11.XGetWindowProperty(dpy, win, A(_NET_FRAME_EXTENTS), 0, 4, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
+			if (atr == XA_CARDINAL && afr == 32 && nir == 4) {
+				extents = (long *)prop;
+				if (l)
+					*l = extents[0];
+				if (r)
+					*r = extents[1];
+				if (t)
+					*t = extents[2];
+				if (b)
+					*b = extents[3];
+				ret = true;
+			}
+			x11.XFree(prop);
+		}
+	}
+	return ret;
+}
+
 static bool
 x11_get_maxsize(int *w, int *h)
 {
@@ -580,12 +611,18 @@ x11_get_maxsize(int *w, int *h)
 	unsigned long bytes_left;
 	unsigned char *prop;
 	long desktop = -1;
+	int l, r, t, b;
 
 	if (dpy == NULL)
 		return false;
 	if (fullscreen) {
-		// TODO: We may not need this if we can wait for ConfigurNotify on fullscreen...
-		return fullscreen_geometry(NULL, NULL, w, h);
+		pthread_mutex_lock(&vstatlock);
+		if (w)
+			*w = vstat.winwidth;
+		if (h)
+			*h = vstat.winheight;
+		pthread_mutex_unlock(&vstatlock);
+		return true;
 	}
 	else {
 		// First, try to get _NET_WORKAREA...
@@ -628,15 +665,9 @@ x11_get_maxsize(int *w, int *h)
 			}
 		}
 		if (maxw > 0 && maxh > 0) {
-			if (A(_NET_FRAME_EXTENTS) != None && win != 0) {
-				if (x11.XGetWindowProperty(dpy, win, A(_NET_FRAME_EXTENTS), 0, 4, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
-					if (atr == XA_CARDINAL && afr == 32 && nir == 4) {
-						ret = (long *)prop;
-						maxw -= ret[0] + ret[1];
-						maxh -= ret[2] + ret[3];
-					}
-					x11.XFree(prop);
-				}
+			if (get_frame_extents(&l, &r, &t, &b)) {
+				maxw -= l + r;
+				maxh -= t + b;
 			}
 		}
 	}
@@ -759,23 +790,26 @@ static void map_window()
 	}
 	sh->flags = 0;
 
-	if (x11_get_maxsize(&sh->max_width,&sh->max_height)) {
-		pthread_mutex_lock(&vstatlock);
-		if (!fullscreen)
+	if (!fullscreen && !fullscreen_pending) {
+		if (x11_get_maxsize(&sh->max_width,&sh->max_height)) {
+			pthread_mutex_lock(&vstatlock);
 			bitmap_get_scaled_win_size(bitmap_double_mult_inside(sh->max_width, sh->max_height), &sh->max_width, &sh->max_height, sh->max_width, sh->max_height);
-	}
-	else {
-		pthread_mutex_lock(&vstatlock);
-		bitmap_get_scaled_win_size(7.0, &sh->max_width, &sh->max_height, 0, 0);
-	}
-	sh->flags |= PMaxSize;
+		}
+		else {
+			pthread_mutex_lock(&vstatlock);
+			bitmap_get_scaled_win_size(7.0, &sh->max_width, &sh->max_height, 0, 0);
+		}
+		sh->flags |= PMaxSize;
 
-	bitmap_get_scaled_win_size(x_cvstat.scaling, &sh->base_width, &sh->base_height, 0, 0);
-	sh->flags |= PBaseSize;
+		bitmap_get_scaled_win_size(x_cvstat.scaling, &sh->base_width, &sh->base_height, 0, 0);
+		sh->flags |= PBaseSize;
 
-	sh->width = sh->base_width;
-	sh->height = sh->base_height;
-	sh->flags |= PSize;
+		sh->width = sh->base_width;
+		sh->height = sh->base_height;
+		sh->flags |= PSize;
+	}
+	else
+		pthread_mutex_lock(&vstatlock);
 
 	bitmap_get_scaled_win_size(1.0, &sh->min_width, &sh->min_height, 0, 0);
 	sh->flags |= PMinSize;
@@ -1052,14 +1086,14 @@ static int init_window()
 }
 
 static bool
-send_fullscreen(bool set)
+send_fullscreen(bool set, int x, int y)
 {
-	static bool last = false;
 	XEvent ev = {0};
 	bool ret = false;
+	int l, t;
 
 	if (A(_NET_WM_STATE) != None && A(_NET_WM_STATE_FULLSCREEN) != None) {
-		if (last != set) {
+		if (fullscreen != set) {
 			ev.xclient.type = ClientMessage;
 			ev.xclient.serial = 0; // Populated by XSendEvent
 			ev.xclient.send_event = True; // Populated by XSendEvent
@@ -1071,12 +1105,23 @@ send_fullscreen(bool set)
 			ev.xclient.data.l[0] = set ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
 			ev.xclient.data.l[1] = A(_NET_WM_STATE_FULLSCREEN);
 			ev.xclient.data.l[3] = 1;
-			if (set)
-				fullscreen_pending = true;
+			fullscreen_pending = true;
+			if (set) {
+				saved_xpos = x;
+				saved_ypos = y;
+				if (get_frame_extents(&l, NULL, &t, NULL)) {
+					saved_xpos -= l;
+					saved_ypos -= t;
+				}
+				pthread_mutex_lock(&vstatlock);
+				saved_width = vstat.winwidth;
+				saved_height = vstat.winheight;
+				saved_scaling = vstat.scaling;
+				pthread_mutex_unlock(&vstatlock);
+			}
 			ret = x11.XSendEvent(dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &ev) != 0;
 			if (ret) {
 				x11.XFlush(dpy);
-				last = set;
 			}
 		}
 		else
@@ -1095,38 +1140,37 @@ static void resize_window()
 	bool resize;
 	double new_scaling;
 
+	/*
+	 * Don't allow resizing the window when we're in fullscreen mode
+	 * or we're transitioning to/from fullscreen modes
+	 */
+	if (fullscreen || fullscreen_pending)
+		return;
 	pthread_mutex_lock(&vstatlock);
-	if (fullscreen && send_fullscreen(true)) {
-		cio_api.mode = CIOLIB_MODE_X_FULLSCREEN;
-	}
-	else {
-		send_fullscreen(false);
-		fullscreen = false;
-		cio_api.mode = CIOLIB_MODE_X;
-		new_scaling = x_cvstat.scaling;
-		bitmap_get_scaled_win_size(new_scaling, &width, &height, 0, 0);
-		// TODO: If we're in fullscreen mode, we don't get the decoration sizes...
-		if (x11_get_maxsize(&max_width, &max_height)) {
-			if (width > max_width || height > max_height) {
-				new_scaling = bitmap_double_mult_inside(max_width, max_height);
-				bitmap_get_scaled_win_size(new_scaling, &width, &height, 0, 0);
-			}
+	cio_api.mode = CIOLIB_MODE_X;
+	new_scaling = x_cvstat.scaling;
+	bitmap_get_scaled_win_size(new_scaling, &width, &height, 0, 0);
+	if (x11_get_maxsize(&max_width, &max_height)) {
+		if (width > max_width || height > max_height) {
+			new_scaling = bitmap_double_mult_inside(max_width, max_height);
+			bitmap_get_scaled_win_size(new_scaling, &width, &height, 0, 0);
 		}
-		new_scaling = bitmap_double_mult_inside(width, height);
-		if (width == vstat.winwidth && height == vstat.winheight) {
-			if (new_scaling != vstat.scaling) {
-				vstat.scaling = x_cvstat.scaling = new_scaling;
-				pthread_mutex_unlock(&vstatlock);
-				resize_xim();
-			}
-			else
-				pthread_mutex_unlock(&vstatlock);
-			return;
+	}
+	new_scaling = bitmap_double_mult_inside(width, height);
+	if (width == vstat.winwidth && height == vstat.winheight) {
+		if (new_scaling != vstat.scaling) {
+			vstat.scaling = x_cvstat.scaling = new_scaling;
+			pthread_mutex_unlock(&vstatlock);
+			resize_xim();
 		}
-		resize = new_scaling != vstat.scaling;
-		x_cvstat.scaling = vstat.scaling;
-		if (resize)
-			x11.XResizeWindow(dpy, win, width, height);
+		else
+			pthread_mutex_unlock(&vstatlock);
+		return;
+	}
+	resize = new_scaling != vstat.scaling;
+	x_cvstat.scaling = vstat.scaling;
+	if (resize) {
+		x11.XResizeWindow(dpy, win, width, height);
 	}
 	pthread_mutex_unlock(&vstatlock);
 
@@ -1191,17 +1235,12 @@ static int init_mode(int mode)
 
 static int video_init()
 {
-	/* If we are running under X, get a connection to the X server and create
-	   an empty window of size (1, 1). It makes a couple of init functions a
-	   lot easier. */
-
 	pthread_mutex_lock(&vstatlock);
 	x_internal_scaling = (ciolib_initial_scaling_type == CIOLIB_SCALING_INTERNAL);
 	if (ciolib_initial_scaling != 0.0)
 		x_cvstat.scaling = vstat.scaling = ciolib_initial_scaling;
 	if (x_cvstat.scaling < 1.0 || vstat.scaling < 1.0)
 		x_cvstat.scaling = vstat.scaling = 1.0;
-	/* Initialize mode 3 (text, 80x25, 16 colors) */
 	if(load_vmode(&vstat, ciolib_initial_mode)) {
 		pthread_mutex_unlock(&vstatlock);
 		return(-1);
@@ -1403,12 +1442,6 @@ local_draw_rect(struct rectlist *rect)
 static void handle_resize_event(int width, int height, bool map)
 {
 	pthread_mutex_lock(&vstatlock);
-	if (fullscreen && !map && !fullscreen_pending) {
-		if ((width != x_cvstat.winwidth || height != x_cvstat.winheight)) {
-			fullscreen = false;
-			cio_api.mode = CIOLIB_MODE_X;
-  		}
-	}
 	x_cvstat.winwidth = vstat.winwidth = width;
 	x_cvstat.winheight = vstat.winheight = height;
 	vstat.scaling = bitmap_double_mult_inside(width, height);
@@ -1549,14 +1582,10 @@ is_fullscreen(void)
 }
 
 static void
-handle_configuration(int x, int y, int w, int h, bool map)
+handle_configuration(int w, int h, bool map)
 {
 	bool resize = false;
 
-	if ((x11_window_xpos != x || x11_window_ypos != y)) {
-		x11_window_xpos = x;
-		x11_window_ypos = y;
-	}
 	pthread_mutex_lock(&vstatlock);
 	if (w != vstat.winwidth || h != vstat.winheight)
 		resize = true;
@@ -1567,6 +1596,7 @@ handle_configuration(int x, int y, int w, int h, bool map)
 
 static int x11_event(XEvent *ev)
 {
+	bool resize;
 	int x, y, w, h;
 
 	if (x11.XFilterEvent(ev, win))
@@ -1587,17 +1617,44 @@ static int x11_event(XEvent *ev)
 			break;
 		case PropertyNotify:
 			if (A(_NET_FRAME_EXTENTS) != None) {
-				if (ev->xproperty.atom == A(_NET_FRAME_EXTENTS))
+				if (ev->xproperty.atom == A(_NET_FRAME_EXTENTS)) {
 					map_window();
+				}
 			}
 			if (A(_NET_WM_STATE) != None) {
 				if (ev->xproperty.atom == A(_NET_WM_STATE)) {
-					if (fullscreen_pending && is_fullscreen()) {
-						fullscreen_pending = false;
-						if (fullscreen_geometry(&x, &y, &w, &h)) {
-							if (x_cvstat.winwidth != w || x_cvstat.winheight != h) {
-								x_cvstat.winwidth = w;
-								x_cvstat.winheight = h;
+					fullscreen_pending = false;
+					if (is_fullscreen()) {
+						if (!fullscreen) {
+							fullscreen = true;
+							if (fullscreen_geometry(&x, &y, &w, &h)) {
+								if (x_cvstat.winwidth != w || x_cvstat.winheight != h) {
+									x_cvstat.winwidth = w;
+									x_cvstat.winheight = h;
+								}
+							}
+						}
+					}
+					else {
+						resize = false;
+						if (fullscreen) {
+							fullscreen = false;
+							x_cvstat.scaling = saved_scaling;
+							pthread_mutex_lock(&vstatlock);
+							/*
+							 * Mode may have changed while in fullscreen... recalculate scaling to
+							 * fit inside the old window size
+							 */
+							bitmap_get_scaled_win_size(saved_scaling, &w, &h, saved_width, saved_height);
+							if (w != vstat.winwidth || h != vstat.winheight)
+								resize = true;
+							pthread_mutex_unlock(&vstatlock);
+							x_cvstat.winwidth = w;
+							x_cvstat.winheight = h;
+							if (resize)
+								x11.XMoveResizeWindow(dpy, win, saved_xpos, saved_ypos, w, h);
+							else {
+								x11.XMoveWindow(dpy, win, saved_xpos, saved_ypos);
 							}
 						}
 					}
@@ -1606,26 +1663,22 @@ static int x11_event(XEvent *ev)
 			break;
 		/* Graphics related events */
 		case ConfigureNotify: {
-			int ax, ay;
-			Window cr;
-
-			// TODO: Maybe we care about parent events?
+			/*
+			 * NOTE: The x/y values in the event are relative to root of send_event is true, and
+			 * relative to the parent (which is the above member) if send_event is false.  Trying
+			 * to translate from parent to root in here is a bad idea as there's a race condition.
+			 * Basically, if we care about the x/y pos, we should not use it when send_event is
+			 * false... if that happens, the position is unknown and we would need to explicitly
+			 * query it, or wait for some other event (key, mouse, etc) to give us a root-relative
+			 * value.
+			 */
 			if (ev->xconfigure.window == win) {
-				// TODO: Verify this hack...
-				if (ev->xconfigure.above != None)
-					x11.XTranslateCoordinates(dpy, ev->xconfigure.window, root, ev->xconfigure.x, ev->xconfigure.y, &ax, &ay, &cr);
-				else {
-					ax = ev->xconfigure.x;
-					ay = ev->xconfigure.y;
-				}
 				if (map_pending) {
-					pending_xpos = ax;
-					pending_ypos = ay;
 					pending_width = ev->xconfigure.width;
 					pending_height = ev->xconfigure.height;
 				}
 				else {
-					handle_configuration(ax, ay, ev->xconfigure.width, ev->xconfigure.height, false);
+					handle_configuration(ev->xconfigure.width, ev->xconfigure.height, false);
 				}
 			}
 			break;
@@ -1633,7 +1686,7 @@ static int x11_event(XEvent *ev)
 		case MapNotify:
 			if (map_pending) {
 				map_pending = false;
-				handle_configuration(pending_xpos, pending_ypos, pending_width, pending_height, true);
+				handle_configuration(pending_width, pending_height, true);
 			}
 			break;
 		case NoExpose:
@@ -1869,8 +1922,7 @@ static int x11_event(XEvent *ev)
 							case XK_KP_Enter:
 								if (ev->xkey.state & Mod1Mask) {
 									// ALT-Enter, toggle full-screen
-									fullscreen = !fullscreen;
-									resize_window();
+									send_fullscreen(!fullscreen, ev->xkey.x_root - ev->xkey.x, ev->xkey.y_root - ev->xkey.y);
 								}
 								scan = 28;
 								goto docode;
diff --git a/src/conio/x_events.h b/src/conio/x_events.h
index c3777f2be0cf1d1199d7acbb61d9fb87477abb07..524327bb34a83e54881a6f779fbb68f12baa079f 100644
--- a/src/conio/x_events.h
+++ b/src/conio/x_events.h
@@ -160,8 +160,6 @@ extern sem_t	pastebuf_used;
 extern Atom	copybuf_format;
 extern sem_t	init_complete;
 extern sem_t	mode_set;
-extern int x11_window_xpos;
-extern int x11_window_ypos;
 extern int x11_initialized;
 extern struct video_stats x_cvstat;
 extern bool xrender_found;