3434#include <wlr/types/wlr_scene.h>
3535#include <wlr/types/wlr_xdg_shell.h>
3636#include <wlr/util/box.h>
37+ #include <wlr/version.h>
3738#undef WLR_USE_UNSTABLE
3839
3940#include "server.h"
@@ -109,6 +110,8 @@ struct wlmaker_xdg_toplevel {
109110 uint32_t (* _set_size )(struct wlr_xdg_toplevel * , int32_t , int32_t );
110111 /** Injected method for wlr_xdg_toplevel_set_activated(). */
111112 uint32_t (* _set_activated )(struct wlr_xdg_toplevel * , bool );
113+ /** Injected method for wlr_surface_get_extents(). */
114+ void (* _get_extents )(struct wlr_surface * , struct wlr_box * );
112115
113116 /** Serial of the most recent commit() call. */
114117 uint32_t committed_serial ;
@@ -153,7 +156,8 @@ struct wlmaker_xdg_toplevel *_wlmaker_xdg_toplevel_create_injected(
153156 uint32_t (* _set_maximized )(struct wlr_xdg_toplevel * , bool ),
154157 uint32_t (* _set_fullscreen )(struct wlr_xdg_toplevel * , bool ),
155158 uint32_t (* _set_size )(struct wlr_xdg_toplevel * , int32_t , int32_t ),
156- uint32_t (* _set_activated )(struct wlr_xdg_toplevel * , bool ));
159+ uint32_t (* _set_activated )(struct wlr_xdg_toplevel * , bool ),
160+ void (* _get_extents )(struct wlr_surface * , struct wlr_box * ));
157161static void _wlmaker_xdg_toplevel_flush_properties (
158162 struct wlmaker_xdg_toplevel * wxt_ptr );
159163static void _wlmaker_xdg_toplevel_try_map (
@@ -233,7 +237,13 @@ struct wlmaker_xdg_toplevel *wlmaker_xdg_toplevel_create(
233237 wlr_xdg_toplevel_set_maximized ,
234238 wlr_xdg_toplevel_set_fullscreen ,
235239 wlr_xdg_toplevel_set_size ,
236- wlr_xdg_toplevel_set_activated );
240+ wlr_xdg_toplevel_set_activated ,
241+ #if WLR_VERSION_NUM >= (19 << 8 )
242+ wlr_surface_get_extents
243+ #else
244+ wlr_surface_get_extends
245+ #endif
246+ );
237247}
238248
239249/* ------------------------------------------------------------------------- */
@@ -303,7 +313,8 @@ struct wlmaker_xdg_toplevel *_wlmaker_xdg_toplevel_create_injected(
303313 uint32_t (* _set_maximized )(struct wlr_xdg_toplevel * , bool ),
304314 uint32_t (* _set_fullscreen )(struct wlr_xdg_toplevel * , bool ),
305315 uint32_t (* _set_size )(struct wlr_xdg_toplevel * , int32_t , int32_t ),
306- uint32_t (* _set_activated )(struct wlr_xdg_toplevel * , bool ))
316+ uint32_t (* _set_activated )(struct wlr_xdg_toplevel * , bool ),
317+ void (* _get_extents )(struct wlr_surface * , struct wlr_box * ))
307318{
308319 // Guard clause: Must have a base. */
309320 if (NULL == wlr_xdg_toplevel_ptr -> base ) {
@@ -321,6 +332,7 @@ struct wlmaker_xdg_toplevel *_wlmaker_xdg_toplevel_create_injected(
321332 wlmaker_xdg_toplevel_ptr -> _set_fullscreen = _set_fullscreen ;
322333 wlmaker_xdg_toplevel_ptr -> _set_size = _set_size ;
323334 wlmaker_xdg_toplevel_ptr -> _set_activated = _set_activated ;
335+ wlmaker_xdg_toplevel_ptr -> _get_extents = _get_extents ;
324336
325337 if (!wlmtk_base_init (& wlmaker_xdg_toplevel_ptr -> base , NULL )) goto error ;
326338
@@ -732,10 +744,14 @@ void _wlmaker_xdg_toplevel_handle_surface_commit(
732744 struct wlr_xdg_surface * wlr_xdg_surface_ptr =
733745 wxt_ptr -> wlr_xdg_toplevel_ptr -> base ;
734746
747+ struct wlr_box geo = wxt_ptr -> wlr_xdg_toplevel_ptr -> base -> current .geometry ;
748+ if (0 >= geo .width && 0 >= geo .height ) {
749+ wxt_ptr -> _get_extents (
750+ wxt_ptr -> wlr_xdg_toplevel_ptr -> base -> surface ,
751+ & geo );
752+ }
735753 wlmtk_window_commit_size (
736- wxt_ptr -> window_ptr ,
737- wxt_ptr -> wlr_xdg_toplevel_ptr -> base -> current .geometry .width ,
738- wxt_ptr -> wlr_xdg_toplevel_ptr -> base -> current .geometry .height );
754+ wxt_ptr -> window_ptr , geo .width - geo .x , geo .height - geo .y );
739755
740756 if (wxt_ptr -> wlr_xdg_toplevel_ptr -> current .fullscreen !=
741757 wlmtk_window_is_fullscreen (wxt_ptr -> window_ptr )) {
@@ -945,7 +961,7 @@ uint32_t _wlmaker_xdg_toplevel_fake_set_fullscreen(
945961 return 0 ;
946962}
947963
948- /** A fake for wlr_xdg_toplevel_set_size(). Recods the call. */
964+ /** A fake for wlr_xdg_toplevel_set_size(). Records the call. */
949965uint32_t _wlmaker_xdg_toplevel_fake_set_size (
950966 struct wlr_xdg_toplevel * wlr_xdg_toplevel_ptr ,
951967 int32_t width ,
@@ -960,7 +976,7 @@ uint32_t _wlmaker_xdg_toplevel_fake_set_size(
960976 return 0 ;
961977}
962978
963- /** A fake for wlr_xdg_toplevel_set_activated(). Recods the call. */
979+ /** A fake for wlr_xdg_toplevel_set_activated(). Records the call. */
964980uint32_t _wlmaker_xdg_toplevel_fake_set_activated (
965981 struct wlr_xdg_toplevel * wlr_xdg_toplevel_ptr ,
966982 __UNUSED__ bool activated )
@@ -972,6 +988,22 @@ uint32_t _wlmaker_xdg_toplevel_fake_set_activated(
972988 return 0 ;
973989}
974990
991+ /** A fake for wlr_surface_get_extents(). Sets box to empty. */
992+ void _wlmaker_xdg_toplevel_fake_get_extents_empty (
993+ __UNUSED__ struct wlr_surface * wlr_surface_ptr ,
994+ struct wlr_box * box_ptr )
995+ {
996+ * box_ptr = (struct wlr_box ){};
997+ }
998+
999+ /** A fake for wlr_surface_get_extents(). Sets box to fixed size. */
1000+ void _wlmaker_xdg_toplevel_fake_get_extents_64x32 (
1001+ __UNUSED__ struct wlr_surface * wlr_surface_ptr ,
1002+ struct wlr_box * box_ptr )
1003+ {
1004+ * box_ptr = (struct wlr_box ){ .width = 64 , .height = 32 };
1005+ }
1006+
9751007/* == Unit tests =========================================================== */
9761008
9771009static void * _wlmaker_xdg_toplevel_test_setup (void );
@@ -982,6 +1014,7 @@ static void _wlmaker_xdg_toplevel_test_fullscreen(bs_test_t *test_ptr);
9821014static void _wlmaker_xdg_toplevel_test_size (bs_test_t * test_ptr );
9831015static void _wlmaker_xdg_toplevel_test_activated (bs_test_t * test_ptr );
9841016static void _wlmaker_xdg_toplevel_test_map (bs_test_t * test_ptr );
1017+ static void _wlmaker_xdg_toplevel_test_map_nogeo (bs_test_t * test_ptr );
9851018
9861019/** Unit test cases. */
9871020const bs_test_case_t _test_cases [] = {
@@ -990,6 +1023,7 @@ const bs_test_case_t _test_cases[] = {
9901023 { true, "size" , _wlmaker_xdg_toplevel_test_size },
9911024 { true, "activated" , _wlmaker_xdg_toplevel_test_activated },
9921025 { true, "map" , _wlmaker_xdg_toplevel_test_map },
1026+ { true, "map_nogeo" , _wlmaker_xdg_toplevel_test_map_nogeo },
9931027 BS_TEST_CASE_SENTINEL ()
9941028};
9951029
@@ -1007,6 +1041,7 @@ void *_wlmaker_xdg_toplevel_test_setup(void)
10071041 struct _xdg_toplevel_test_data * td_ptr = logged_calloc (
10081042 1 , sizeof (struct _xdg_toplevel_test_data ));
10091043 if (NULL == td_ptr ) return NULL ;
1044+ td_ptr -> wlr_surface .data = td_ptr ;
10101045 td_ptr -> wlr_xdg_surface .surface = & td_ptr -> wlr_surface ;
10111046 td_ptr -> wlr_xdg_toplevel .base = & td_ptr -> wlr_xdg_surface ;
10121047
@@ -1097,7 +1132,8 @@ void _wlmaker_xdg_toplevel_test_maximize(bs_test_t *test_ptr)
10971132 _wlmaker_xdg_toplevel_fake_set_maximized ,
10981133 _wlmaker_xdg_toplevel_fake_set_fullscreen ,
10991134 _wlmaker_xdg_toplevel_fake_set_size ,
1100- _wlmaker_xdg_toplevel_fake_set_activated );
1135+ _wlmaker_xdg_toplevel_fake_set_activated ,
1136+ _wlmaker_xdg_toplevel_fake_get_extents_empty );
11011137 BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
11021138 BS_TEST_VERIFY_EQ (test_ptr , 1 , created .calls );
11031139
@@ -1107,6 +1143,8 @@ void _wlmaker_xdg_toplevel_test_maximize(bs_test_t *test_ptr)
11071143
11081144 // Now we have pending properties. Commit must trigger a `configure`.
11091145 td_ptr -> wlr_xdg_surface .initialized = true; // Ready for configure().
1146+ td_ptr -> wlr_xdg_surface .current .geometry .width = 200 ;
1147+ td_ptr -> wlr_xdg_surface .current .geometry .height = 100 ;
11101148 wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
11111149 BS_TEST_VERIFY_EQ (test_ptr , 1 , td_ptr -> set_maximized_calls );
11121150
@@ -1151,7 +1189,8 @@ void _wlmaker_xdg_toplevel_test_fullscreen(bs_test_t *test_ptr)
11511189 _wlmaker_xdg_toplevel_fake_set_maximized ,
11521190 _wlmaker_xdg_toplevel_fake_set_fullscreen ,
11531191 _wlmaker_xdg_toplevel_fake_set_size ,
1154- _wlmaker_xdg_toplevel_fake_set_activated );
1192+ _wlmaker_xdg_toplevel_fake_set_activated ,
1193+ _wlmaker_xdg_toplevel_fake_get_extents_empty );
11551194 BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
11561195
11571196 // Issued from the window, ie. from the compositor.
@@ -1162,6 +1201,8 @@ void _wlmaker_xdg_toplevel_test_fullscreen(bs_test_t *test_ptr)
11621201
11631202 // Pending properties. Next commit must trigger.
11641203 td_ptr -> wlr_xdg_surface .initialized = true; // Ready for configure().
1204+ td_ptr -> wlr_xdg_surface .current .geometry .width = 200 ;
1205+ td_ptr -> wlr_xdg_surface .current .geometry .height = 100 ;
11651206 wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
11661207 BS_TEST_VERIFY_EQ (test_ptr , 1 , td_ptr -> set_fullscreen_calls );
11671208
@@ -1193,7 +1234,8 @@ void _wlmaker_xdg_toplevel_test_size(bs_test_t *test_ptr)
11931234 _wlmaker_xdg_toplevel_fake_set_maximized ,
11941235 _wlmaker_xdg_toplevel_fake_set_fullscreen ,
11951236 _wlmaker_xdg_toplevel_fake_set_size ,
1196- _wlmaker_xdg_toplevel_fake_set_activated );
1237+ _wlmaker_xdg_toplevel_fake_set_activated ,
1238+ _wlmaker_xdg_toplevel_fake_get_extents_empty );
11971239 BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
11981240
11991241 // Issued from the window, ie. from the compositor.
@@ -1204,6 +1246,8 @@ void _wlmaker_xdg_toplevel_test_size(bs_test_t *test_ptr)
12041246
12051247 // Pending properties. Next commit must trigger.
12061248 td_ptr -> wlr_xdg_surface .initialized = true; // Ready for configure().
1249+ td_ptr -> wlr_xdg_surface .current .geometry .width = 200 ;
1250+ td_ptr -> wlr_xdg_surface .current .geometry .height = 100 ;
12071251 wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
12081252 BS_TEST_VERIFY_EQ (test_ptr , 1 , td_ptr -> set_size_calls );
12091253 BS_TEST_VERIFY_EQ (test_ptr , 10 , td_ptr -> set_size_width );
@@ -1226,7 +1270,8 @@ void _wlmaker_xdg_toplevel_test_activated(bs_test_t *test_ptr)
12261270 _wlmaker_xdg_toplevel_fake_set_maximized ,
12271271 _wlmaker_xdg_toplevel_fake_set_fullscreen ,
12281272 _wlmaker_xdg_toplevel_fake_set_size ,
1229- _wlmaker_xdg_toplevel_fake_set_activated );
1273+ _wlmaker_xdg_toplevel_fake_set_activated ,
1274+ _wlmaker_xdg_toplevel_fake_get_extents_empty );
12301275 BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
12311276
12321277 // Issued from the window, ie. from the compositor.
@@ -1237,6 +1282,8 @@ void _wlmaker_xdg_toplevel_test_activated(bs_test_t *test_ptr)
12371282
12381283 // Pending properties. Next commit must trigger.
12391284 td_ptr -> wlr_xdg_surface .initialized = true; // Ready for configure().
1285+ td_ptr -> wlr_xdg_surface .current .geometry .width = 200 ;
1286+ td_ptr -> wlr_xdg_surface .current .geometry .height = 100 ;
12401287 wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
12411288 BS_TEST_VERIFY_EQ (test_ptr , 1 , td_ptr -> set_activated_calls );
12421289
@@ -1257,7 +1304,8 @@ void _wlmaker_xdg_toplevel_test_map(bs_test_t *test_ptr)
12571304 _wlmaker_xdg_toplevel_fake_set_maximized ,
12581305 _wlmaker_xdg_toplevel_fake_set_fullscreen ,
12591306 _wlmaker_xdg_toplevel_fake_set_size ,
1260- _wlmaker_xdg_toplevel_fake_set_activated );
1307+ _wlmaker_xdg_toplevel_fake_set_activated ,
1308+ _wlmaker_xdg_toplevel_fake_get_extents_empty );
12611309 BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
12621310 wlmtk_window_t * w = wxt_ptr -> window_ptr ; // for convenience.
12631311
@@ -1266,7 +1314,7 @@ void _wlmaker_xdg_toplevel_test_map(bs_test_t *test_ptr)
12661314 wxt_ptr -> surface_ptr = NULL ;
12671315
12681316 // Situation 1: Initial map call, but surface has size (0x0) yet.
1269- // => ill not be mapped yet, but only after a commit with non-zero size.
1317+ // => will not be mapped yet, but only after a commit with non-zero size.
12701318 wl_signal_emit (& td_ptr -> wlr_surface .events .map , NULL );
12711319 BS_TEST_VERIFY_EQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
12721320
@@ -1277,6 +1325,57 @@ void _wlmaker_xdg_toplevel_test_map(bs_test_t *test_ptr)
12771325 td_ptr -> wlr_xdg_surface .current .geometry .height = 100 ;
12781326 wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
12791327 BS_TEST_VERIFY_NEQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1328+ WLMTK_TEST_VERIFY_WLRBOX_EQ (
1329+ test_ptr , 0 , 0 , 200 , 100 , wlmtk_window_get_size (w ));
1330+
1331+ wl_signal_emit (& td_ptr -> wlr_surface .events .unmap , NULL );
1332+ BS_TEST_VERIFY_EQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1333+
1334+ // Situation 2: Size is set. Must get mapped upon surface 'map'.
1335+ wl_signal_emit (& td_ptr -> wlr_surface .events .map , NULL );
1336+ BS_TEST_VERIFY_NEQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1337+
1338+ wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
1339+ BS_TEST_VERIFY_NEQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1340+
1341+ wl_signal_emit (& td_ptr -> wlr_surface .events .unmap , NULL );
1342+ BS_TEST_VERIFY_EQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1343+
1344+ wlmaker_xdg_toplevel_destroy (wxt_ptr );
1345+ }
1346+
1347+ /* ------------------------------------------------------------------------- */
1348+ /** Tests surface map calls if no geometry is given. */
1349+ void _wlmaker_xdg_toplevel_test_map_nogeo (bs_test_t * test_ptr )
1350+ {
1351+ struct _xdg_toplevel_test_data * td_ptr =
1352+ BS_ASSERT_NOTNULL (bs_test_context (test_ptr ));
1353+
1354+ struct wlmaker_xdg_toplevel * wxt_ptr =
1355+ _wlmaker_xdg_toplevel_create_injected (
1356+ & td_ptr -> wlr_xdg_toplevel ,
1357+ & td_ptr -> server ,
1358+ _wlmaker_xdg_toplevel_fake_set_maximized ,
1359+ _wlmaker_xdg_toplevel_fake_set_fullscreen ,
1360+ _wlmaker_xdg_toplevel_fake_set_size ,
1361+ _wlmaker_xdg_toplevel_fake_set_activated ,
1362+ _wlmaker_xdg_toplevel_fake_get_extents_64x32 );
1363+ BS_TEST_VERIFY_NEQ_OR_RETURN (test_ptr , NULL , wxt_ptr );
1364+ wlmtk_window_t * w = wxt_ptr -> window_ptr ; // for convenience.
1365+
1366+ // Override the surface element. We cannot actually map it.
1367+ wlmtk_base_set_content_element (& wxt_ptr -> base , NULL );
1368+ wxt_ptr -> surface_ptr = NULL ;
1369+
1370+ // Situation 1: Initial map call. Surface has geometry 0,0, but
1371+ // the extents are 64x32. Will map, with that size.
1372+ wl_signal_emit (& td_ptr -> wlr_surface .events .map , NULL );
1373+ BS_TEST_VERIFY_EQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1374+
1375+ wl_signal_emit (& td_ptr -> wlr_surface .events .commit , NULL );
1376+ BS_TEST_VERIFY_NEQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
1377+ WLMTK_TEST_VERIFY_WLRBOX_EQ (
1378+ test_ptr , 0 , 0 , 64 , 32 , wlmtk_window_get_size (w ));
12801379
12811380 wl_signal_emit (& td_ptr -> wlr_surface .events .unmap , NULL );
12821381 BS_TEST_VERIFY_EQ (test_ptr , NULL , wlmtk_window_get_workspace (w ));
0 commit comments