Index: uspace/lib/display/include/disp_srv.h
===================================================================
--- uspace/lib/display/include/disp_srv.h	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/include/disp_srv.h	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -62,5 +62,8 @@
 	errno_t (*window_move)(void *, sysarg_t, gfx_coord2_t *);
 	errno_t (*window_get_pos)(void *, sysarg_t, gfx_coord2_t *);
+	errno_t (*window_get_max_rect)(void *, sysarg_t, gfx_rect_t *);
 	errno_t (*window_resize)(void *, sysarg_t, gfx_coord2_t *, gfx_rect_t *);
+	errno_t (*window_maximize)(void *, sysarg_t);
+	errno_t (*window_unmaximize)(void *, sysarg_t);
 	errno_t (*window_set_cursor)(void *, sysarg_t, display_stock_cursor_t);
 	errno_t (*get_event)(void *, sysarg_t *, display_wnd_ev_t *);
Index: uspace/lib/display/include/display.h
===================================================================
--- uspace/lib/display/include/display.h	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/include/display.h	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -59,6 +59,9 @@
 extern errno_t display_window_move(display_window_t *, gfx_coord2_t *);
 extern errno_t display_window_get_pos(display_window_t *, gfx_coord2_t *);
+extern errno_t display_window_get_max_rect(display_window_t *, gfx_rect_t *);
 extern errno_t display_window_resize(display_window_t *,
     gfx_coord2_t *, gfx_rect_t *);
+extern errno_t display_window_maximize(display_window_t *);
+extern errno_t display_window_unmaximize(display_window_t *);
 extern errno_t display_window_set_cursor(display_window_t *,
     display_stock_cursor_t);
Index: uspace/lib/display/include/ipc/display.h
===================================================================
--- uspace/lib/display/include/ipc/display.h	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/include/ipc/display.h	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,10 +42,13 @@
 	DISPLAY_WINDOW_CREATE,
 	DISPLAY_WINDOW_DESTROY,
+	DISPLAY_WINDOW_MAXIMIZE,
 	DISPLAY_WINDOW_MOVE,
 	DISPLAY_WINDOW_MOVE_REQ,
 	DISPLAY_WINDOW_GET_POS,
+	DISPLAY_WINDOW_GET_MAX_RECT,
 	DISPLAY_WINDOW_RESIZE,
 	DISPLAY_WINDOW_RESIZE_REQ,
 	DISPLAY_WINDOW_SET_CURSOR,
+	DISPLAY_WINDOW_UNMAXIMIZE,
 	DISPLAY_GET_EVENT,
 	DISPLAY_GET_INFO
Index: uspace/lib/display/include/types/display/wndparams.h
===================================================================
--- uspace/lib/display/include/types/display/wndparams.h	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/include/types/display/wndparams.h	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,5 +43,7 @@
 	wndf_popup = 0x1,
 	/** Set specific initial window position */
-	wndf_setpos = 0x2
+	wndf_setpos = 0x2,
+	/** Window is maximized */
+	wndf_maximized = 0x4
 } display_wnd_flags_t;
 
Index: uspace/lib/display/src/disp_srv.c
===================================================================
--- uspace/lib/display/src/disp_srv.c	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/src/disp_srv.c	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -230,4 +230,48 @@
 }
 
+static void display_window_get_max_rect_srv(display_srv_t *srv,
+    ipc_call_t *icall)
+{
+	sysarg_t wnd_id;
+	ipc_call_t call;
+	gfx_rect_t rect;
+	size_t size;
+	errno_t rc;
+
+	wnd_id = ipc_get_arg1(icall);
+
+	if (srv->ops->window_get_max_rect == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	if (!async_data_read_receive(&call, &size)) {
+		async_answer_0(icall, EREFUSED);
+		return;
+	}
+
+	rc = srv->ops->window_get_max_rect(srv->arg, wnd_id, &rect);
+	if (rc != EOK) {
+		async_answer_0(&call, rc);
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	if (size != sizeof(gfx_rect_t)) {
+		async_answer_0(&call, EINVAL);
+		async_answer_0(icall, EINVAL);
+		return;
+	}
+
+	rc = async_data_read_finalize(&call, &rect, size);
+	if (rc != EOK) {
+		async_answer_0(&call, rc);
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	async_answer_0(icall, EOK);
+}
+
 static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
 {
@@ -306,4 +350,36 @@
 	rc = srv->ops->window_resize(srv->arg, wnd_id, &wresize.offs,
 	    &wresize.nrect);
+	async_answer_0(icall, rc);
+}
+
+static void display_window_maximize_srv(display_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t wnd_id;
+	errno_t rc;
+
+	wnd_id = ipc_get_arg1(icall);
+
+	if (srv->ops->window_maximize == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->ops->window_maximize(srv->arg, wnd_id);
+	async_answer_0(icall, rc);
+}
+
+static void display_window_unmaximize_srv(display_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t wnd_id;
+	errno_t rc;
+
+	wnd_id = ipc_get_arg1(icall);
+
+	if (srv->ops->window_unmaximize == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->ops->window_unmaximize(srv->arg, wnd_id);
 	async_answer_0(icall, rc);
 }
@@ -445,4 +521,7 @@
 			display_window_get_pos_srv(srv, &call);
 			break;
+		case DISPLAY_WINDOW_GET_MAX_RECT:
+			display_window_get_max_rect_srv(srv, &call);
+			break;
 		case DISPLAY_WINDOW_RESIZE_REQ:
 			display_window_resize_req_srv(srv, &call);
@@ -450,4 +529,10 @@
 		case DISPLAY_WINDOW_RESIZE:
 			display_window_resize_srv(srv, &call);
+			break;
+		case DISPLAY_WINDOW_MAXIMIZE:
+			display_window_maximize_srv(srv, &call);
+			break;
+		case DISPLAY_WINDOW_UNMAXIMIZE:
+			display_window_unmaximize_srv(srv, &call);
 			break;
 		case DISPLAY_WINDOW_SET_CURSOR:
Index: uspace/lib/display/src/display.c
===================================================================
--- uspace/lib/display/src/display.c	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/src/display.c	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -350,4 +350,36 @@
 }
 
+/** Get display window maximized rectangle.
+ *
+ * Get the rectangle to which a window would be maximized.
+ *
+ * @param window Window
+ * @param rect Place to store maximized rectangle
+ * @return EOK on success or an error code
+ */
+errno_t display_window_get_max_rect(display_window_t *window, gfx_rect_t *rect)
+{
+	async_exch_t *exch;
+	aid_t req;
+	ipc_call_t answer;
+	errno_t rc;
+
+	exch = async_exchange_begin(window->display->sess);
+	req = async_send_1(exch, DISPLAY_WINDOW_GET_MAX_RECT, window->id,
+	    &answer);
+	rc = async_data_read_start(exch, rect, sizeof (gfx_rect_t));
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
 /** Request a window resize.
  *
@@ -453,4 +485,38 @@
 
 	return EOK;
+}
+
+/** Maximize window.
+ *
+ * @param window Window
+ * @return EOK on success or an error code
+ */
+errno_t display_window_maximize(display_window_t *window)
+{
+	async_exch_t *exch;
+	errno_t rc;
+
+	exch = async_exchange_begin(window->display->sess);
+	rc = async_req_1_0(exch, DISPLAY_WINDOW_MAXIMIZE, window->id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+/** Unmaximize window.
+ *
+ * @param window Window
+ * @return EOK on success or an error code
+ */
+errno_t display_window_unmaximize(display_window_t *window)
+{
+	async_exch_t *exch;
+	errno_t rc;
+
+	exch = async_exchange_begin(window->display->sess);
+	rc = async_req_1_0(exch, DISPLAY_WINDOW_UNMAXIMIZE, window->id);
+	async_exchange_end(exch);
+
+	return rc;
 }
 
Index: uspace/lib/display/test/display.c
===================================================================
--- uspace/lib/display/test/display.c	(revision 552b69f240ec8edc47b2b988d0b23e54621bbde0)
+++ uspace/lib/display/test/display.c	(revision fdf55a3c204ba982dec2e1272d1633955a396f19)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -60,8 +60,11 @@
 static errno_t test_window_move(void *, sysarg_t, gfx_coord2_t *);
 static errno_t test_window_get_pos(void *, sysarg_t, gfx_coord2_t *);
+static errno_t test_window_get_max_rect(void *, sysarg_t, gfx_rect_t *);
 static errno_t test_window_resize_req(void *, sysarg_t, display_wnd_rsztype_t,
     gfx_coord2_t *);
 static errno_t test_window_resize(void *, sysarg_t, gfx_coord2_t *,
     gfx_rect_t *);
+static errno_t test_window_maximize(void *, sysarg_t);
+static errno_t test_window_unmaximize(void *, sysarg_t);
 static errno_t test_window_set_cursor(void *, sysarg_t, display_stock_cursor_t);
 static errno_t test_get_event(void *, sysarg_t *, display_wnd_ev_t *);
@@ -76,6 +79,9 @@
 	.window_move = test_window_move,
 	.window_get_pos = test_window_get_pos,
+	.window_get_max_rect = test_window_get_max_rect,
 	.window_resize_req = test_window_resize_req,
 	.window_resize = test_window_resize,
+	.window_maximize = test_window_maximize,
+	.window_unmaximize = test_window_unmaximize,
 	.window_set_cursor = test_window_set_cursor,
 	.get_event = test_get_event,
@@ -122,4 +128,8 @@
 	gfx_coord2_t get_pos_rpos;
 
+	bool window_get_max_rect_called;
+	sysarg_t get_max_rect_wnd_id;
+	gfx_rect_t get_max_rect_rrect;
+
 	bool window_resize_req_called;
 	sysarg_t resize_req_wnd_id;
@@ -131,4 +141,7 @@
 	gfx_rect_t resize_nbound;
 	sysarg_t resize_wnd_id;
+
+	bool window_maximize_called;
+	bool window_unmaximize_called;
 
 	bool window_set_cursor_called;
@@ -674,4 +687,126 @@
 }
 
+/** display_window_get_max_rect() with server returning error response works. */
+PCUT_TEST(window_get_max_rect_failure)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	gfx_rect_t rect;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EIO;
+	resp.window_get_max_rect_called = false;
+
+	rect.p0.x = 0;
+	rect.p0.y = 0;
+	rect.p1.x = 0;
+	rect.p1.y = 0;
+
+	rc = display_window_get_max_rect(wnd, &rect);
+	PCUT_ASSERT_TRUE(resp.window_get_max_rect_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
+	PCUT_ASSERT_INT_EQUALS(wnd->id, resp.get_max_rect_wnd_id);
+	PCUT_ASSERT_INT_EQUALS(0, rect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(0, rect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(0, rect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(0, rect.p1.y);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** display_window_get_max_rect() with server returning success response works. */
+PCUT_TEST(window_get_max_rect_success)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	gfx_rect_t rect;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EOK;
+	resp.window_get_max_rect_called = false;
+	resp.get_max_rect_rrect.p0.x = 11;
+	resp.get_max_rect_rrect.p0.y = 12;
+	resp.get_max_rect_rrect.p1.x = 13;
+	resp.get_max_rect_rrect.p1.y = 14;
+
+	rect.p0.x = 0;
+	rect.p0.y = 0;
+	rect.p1.x = 0;
+	rect.p1.y = 0;
+
+	rc = display_window_get_max_rect(wnd, &rect);
+	PCUT_ASSERT_TRUE(resp.window_get_max_rect_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
+	PCUT_ASSERT_INT_EQUALS(wnd->id, resp.get_max_rect_wnd_id);
+	PCUT_ASSERT_INT_EQUALS(resp.get_max_rect_rrect.p0.x, rect.p0.x);
+	PCUT_ASSERT_INT_EQUALS(resp.get_max_rect_rrect.p0.y, rect.p0.y);
+	PCUT_ASSERT_INT_EQUALS(resp.get_max_rect_rrect.p1.x, rect.p1.x);
+	PCUT_ASSERT_INT_EQUALS(resp.get_max_rect_rrect.p1.y, rect.p1.y);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
 /** display_window_resize_req() with server returning error response works. */
 PCUT_TEST(window_resize_req_failure)
@@ -908,4 +1043,100 @@
 	PCUT_ASSERT_INT_EQUALS(nrect.p1.x, resp.resize_nbound.p1.x);
 	PCUT_ASSERT_INT_EQUALS(nrect.p1.y, resp.resize_nbound.p1.y);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** display_window_maximize() with server returning error response works. */
+PCUT_TEST(window_maximize_failure)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EIO;
+	resp.window_maximize_called = false;
+
+	rc = display_window_maximize(wnd);
+	PCUT_ASSERT_TRUE(resp.window_maximize_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** display_window_maximize() with server returning success response works. */
+PCUT_TEST(window_maximize_success)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EOK;
+	resp.window_maximize_called = false;
+
+	rc = display_window_maximize(wnd);
+	PCUT_ASSERT_TRUE(resp.window_maximize_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
 
 	display_window_destroy(wnd);
@@ -1719,4 +1950,18 @@
 }
 
+static errno_t test_window_get_max_rect(void *arg, sysarg_t wnd_id,
+    gfx_rect_t *rect)
+{
+	test_response_t *resp = (test_response_t *) arg;
+
+	resp->window_get_max_rect_called = true;
+	resp->get_max_rect_wnd_id = wnd_id;
+
+	if (resp->rc == EOK)
+		*rect = resp->get_max_rect_rrect;
+
+	return resp->rc;
+}
+
 static errno_t test_window_resize_req(void *arg, sysarg_t wnd_id,
     display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
@@ -1740,4 +1985,22 @@
 	resp->resize_offs = *offs;
 	resp->resize_nbound = *nrect;
+	return resp->rc;
+}
+
+static errno_t test_window_maximize(void *arg, sysarg_t wnd_id)
+{
+	test_response_t *resp = (test_response_t *) arg;
+
+	resp->window_maximize_called = true;
+	resp->resize_wnd_id = wnd_id;
+	return resp->rc;
+}
+
+static errno_t test_window_unmaximize(void *arg, sysarg_t wnd_id)
+{
+	test_response_t *resp = (test_response_t *) arg;
+
+	resp->window_unmaximize_called = true;
+	resp->resize_wnd_id = wnd_id;
 	return resp->rc;
 }
