Skip to content

Commit ef80d7e

Browse files
committed
xdg_toplevel: Fixes handling of clients not setting geometry (eg. wlroots compositors), using wlr_surface_get_extents() as fallback.
1 parent 636a7d9 commit ef80d7e

File tree

3 files changed

+114
-16
lines changed

3 files changed

+114
-16
lines changed

doc/ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ See the [Detailed Feature List](FEATURES.md) for details.
5151

5252
* Bug fixes
5353
* [done] Fix crash when changing to different terminal ([#438](https://github.com/phkaeser/wlmaker/issues/438)).
54-
* Fix wlmaker not showing window of wlroots clients ([#439](https://github.com/phkaeser/wlmaker/issues/439)).
54+
* [done] wlmaker not showing window of wlroots clients ([#439](https://github.com/phkaeser/wlmaker/issues/439)).
5555

5656
## [0.7](https://github.com/phkaeser/wlmaker/releases/tag/v0.7)
5757

src/xdg_toplevel.c

Lines changed: 113 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
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 *));
157161
static void _wlmaker_xdg_toplevel_flush_properties(
158162
struct wlmaker_xdg_toplevel *wxt_ptr);
159163
static 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. */
949965
uint32_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. */
964980
uint32_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

9771009
static void *_wlmaker_xdg_toplevel_test_setup(void);
@@ -982,6 +1014,7 @@ static void _wlmaker_xdg_toplevel_test_fullscreen(bs_test_t *test_ptr);
9821014
static void _wlmaker_xdg_toplevel_test_size(bs_test_t *test_ptr);
9831015
static void _wlmaker_xdg_toplevel_test_activated(bs_test_t *test_ptr);
9841016
static 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. */
9871020
const 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));

src/xwl.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
* properties for the window types.
5757
*/
5858

59-
6059
#include "xwl.h"
6160

6261
#if defined(WLMAKER_HAVE_XWAYLAND)

0 commit comments

Comments
 (0)