@@ -1348,17 +1348,46 @@ void WaylandThread::_xdg_toplevel_on_configure(void *data, struct xdg_toplevel *
13481348 // Expect the window to be in a plain state. It will get properly set if the
13491349 // compositor reports otherwise below.
13501350 ws->mode = DisplayServer::WINDOW_MODE_WINDOWED ;
1351+ ws->maximized = false ;
1352+ ws->fullscreen = false ;
1353+ ws->resizing = false ;
1354+ ws->tiled_left = false ;
1355+ ws->tiled_right = false ;
1356+ ws->tiled_top = false ;
1357+ ws->tiled_bottom = false ;
13511358 ws->suspended = false ;
13521359
13531360 uint32_t *state = nullptr ;
13541361 wl_array_for_each (state, states) {
13551362 switch (*state) {
13561363 case XDG_TOPLEVEL_STATE_MAXIMIZED : {
13571364 ws->mode = DisplayServer::WINDOW_MODE_MAXIMIZED ;
1365+ ws->maximized = true ;
13581366 } break ;
13591367
13601368 case XDG_TOPLEVEL_STATE_FULLSCREEN : {
13611369 ws->mode = DisplayServer::WINDOW_MODE_FULLSCREEN ;
1370+ ws->fullscreen = true ;
1371+ } break ;
1372+
1373+ case XDG_TOPLEVEL_STATE_RESIZING : {
1374+ ws->resizing = true ;
1375+ } break ;
1376+
1377+ case XDG_TOPLEVEL_STATE_TILED_LEFT : {
1378+ ws->tiled_left = true ;
1379+ } break ;
1380+
1381+ case XDG_TOPLEVEL_STATE_TILED_RIGHT : {
1382+ ws->tiled_right = true ;
1383+ } break ;
1384+
1385+ case XDG_TOPLEVEL_STATE_TILED_TOP : {
1386+ ws->tiled_top = true ;
1387+ } break ;
1388+
1389+ case XDG_TOPLEVEL_STATE_TILED_BOTTOM : {
1390+ ws->tiled_bottom = true ;
13621391 } break ;
13631392
13641393 case XDG_TOPLEVEL_STATE_SUSPENDED : {
@@ -1537,15 +1566,42 @@ void WaylandThread::libdecor_frame_on_configure(struct libdecor_frame *frame, st
15371566 // Expect the window to be in a plain state. It will get properly set if the
15381567 // compositor reports otherwise below.
15391568 ws->mode = DisplayServer::WINDOW_MODE_WINDOWED ;
1569+ ws->maximized = false ;
1570+ ws->fullscreen = false ;
1571+ ws->resizing = false ;
1572+ ws->tiled_left = false ;
1573+ ws->tiled_right = false ;
1574+ ws->tiled_top = false ;
1575+ ws->tiled_bottom = false ;
15401576 ws->suspended = false ;
15411577
15421578 if (libdecor_configuration_get_window_state (configuration, &window_state)) {
15431579 if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED ) {
15441580 ws->mode = DisplayServer::WINDOW_MODE_MAXIMIZED ;
1581+ ws->maximized = true ;
15451582 }
15461583
15471584 if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN ) {
15481585 ws->mode = DisplayServer::WINDOW_MODE_FULLSCREEN ;
1586+ ws->fullscreen = true ;
1587+ }
1588+
1589+ // libdecor doesn't have the resizing state for whatever reason.
1590+
1591+ if (window_state & LIBDECOR_WINDOW_STATE_TILED_LEFT ) {
1592+ ws->tiled_left = true ;
1593+ }
1594+
1595+ if (window_state & LIBDECOR_WINDOW_STATE_TILED_RIGHT ) {
1596+ ws->tiled_right = true ;
1597+ }
1598+
1599+ if (window_state & LIBDECOR_WINDOW_STATE_TILED_TOP ) {
1600+ ws->tiled_top = true ;
1601+ }
1602+
1603+ if (window_state & LIBDECOR_WINDOW_STATE_TILED_BOTTOM ) {
1604+ ws->tiled_bottom = true ;
15491605 }
15501606
15511607 if (window_state & LIBDECOR_WINDOW_STATE_SUSPENDED ) {
@@ -3997,6 +4053,58 @@ const WaylandThread::WindowState *WaylandThread::window_get_state(DisplayServer:
39974053 return windows.getptr (p_window_id);
39984054}
39994055
4056+ Size2i WaylandThread::window_set_size (DisplayServer::WindowID p_window_id, const Size2i &p_size) {
4057+ ERR_FAIL_COND_V (!windows.has (p_window_id), p_size);
4058+ WindowState &ws = windows[p_window_id];
4059+
4060+ double window_scale = window_state_get_scale_factor (&ws);
4061+
4062+ if (ws.maximized ) {
4063+ // Can't do anything.
4064+ return scale_vector2i (ws.rect .size , window_scale);
4065+ }
4066+
4067+ Size2i new_size = scale_vector2i (p_size, 1 / window_scale);
4068+
4069+ if (ws.tiled_left && ws.tiled_right ) {
4070+ // Tiled left and right, we shouldn't change from our current width or else
4071+ // it'll look wonky.
4072+ new_size.width = ws.rect .size .width ;
4073+ }
4074+
4075+ if (ws.tiled_top && ws.tiled_bottom ) {
4076+ // Tiled top and bottom. Same as above, but for the height.
4077+ new_size.height = ws.rect .size .height ;
4078+ }
4079+
4080+ if (ws.resizing && ws.rect .size .width > 0 && ws.rect .size .height > 0 ) {
4081+ // The spec says that we shall not resize further than the config size. We can
4082+ // resize less than that though.
4083+ new_size = new_size.min (ws.rect .size );
4084+ }
4085+
4086+ // NOTE: Older versions of libdecor (~2022) do not have a way to get the max
4087+ // content size. Let's also check for its pointer so that we can preserve
4088+ // compatibility with older distros.
4089+ if (ws.libdecor_frame && libdecor_frame_get_max_content_size) {
4090+ int max_width = new_size.width ;
4091+ int max_height = new_size.height ;
4092+
4093+ // NOTE: Max content size is dynamic on libdecor, as plugins can override it
4094+ // to accommodate their decorations.
4095+ libdecor_frame_get_max_content_size (ws.libdecor_frame , &max_width, &max_height);
4096+
4097+ if (max_width > 0 && max_height > 0 ) {
4098+ new_size.width = MIN (new_size.width , max_width);
4099+ new_size.height = MIN (new_size.height , max_height);
4100+ }
4101+ }
4102+
4103+ window_state_update_size (&ws, new_size.width , new_size.height );
4104+
4105+ return scale_vector2i (new_size, window_scale);
4106+ }
4107+
40004108void WaylandThread::beep () const {
40014109 if (registry.xdg_system_bell ) {
40024110 xdg_system_bell_v1_ring (registry.xdg_system_bell , nullptr );
@@ -4177,8 +4285,12 @@ bool WaylandThread::window_can_set_mode(DisplayServer::WindowID p_window_id, Dis
41774285 };
41784286
41794287 case DisplayServer::WINDOW_MODE_MAXIMIZED : {
4180- // NOTE: libdecor doesn't seem to have a maximize capability query?
4181- // The fact that there's a fullscreen one makes me suspicious.
4288+ if (ws.libdecor_frame ) {
4289+ // NOTE: libdecor doesn't seem to have a maximize capability query?
4290+ // The fact that there's a fullscreen one makes me suspicious. Anyways,
4291+ // let's act as if we always can.
4292+ return true ;
4293+ }
41824294 return ws.can_maximize ;
41834295 };
41844296
@@ -5436,7 +5548,9 @@ void WaylandThread::destroy() {
54365548 zwp_tablet_tool_v2_destroy (tool);
54375549 }
54385550
5439- zwp_text_input_v3_destroy (ss->wp_text_input );
5551+ if (ss->wp_text_input ) {
5552+ zwp_text_input_v3_destroy (ss->wp_text_input );
5553+ }
54405554
54415555 memdelete (ss);
54425556 }
0 commit comments