Skip to content

Commit 23d9a39

Browse files
authored
Merge pull request #70 from WayfireWM/fix-crash
Fix crash
2 parents 04437b3 + b4cce3a commit 23d9a39

4 files changed

Lines changed: 134 additions & 11 deletions

File tree

proto/wlr-foreign-toplevel-management-unstable-v1.xml

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
THIS SOFTWARE.
2626
</copyright>
2727

28-
<interface name="zwlr_foreign_toplevel_manager_v1" version="1">
28+
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
2929
<description summary="list and control opened apps">
3030
The purpose of this protocol is to enable the creation of taskbars
3131
and docks by providing them with a list of opened applications and
@@ -68,7 +68,7 @@
6868
</event>
6969
</interface>
7070

71-
<interface name="zwlr_foreign_toplevel_handle_v1" version="1">
71+
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
7272
<description summary="an opened toplevel">
7373
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
7474
window. Each app may have multiple opened toplevels.
@@ -150,9 +150,10 @@
150150
as the states with the same names defined in xdg-toplevel
151151
</description>
152152

153-
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
154-
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
155-
<entry name="activated" value="2" summary="the toplevel is active"/>
153+
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
154+
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
155+
<entry name="activated" value="2" summary="the toplevel is active"/>
156+
<entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
156157
</enum>
157158

158159
<event name="state">
@@ -231,5 +232,39 @@
231232
destruction of the object.
232233
</description>
233234
</request>
235+
236+
<!-- Version 2 additions -->
237+
238+
<request name="set_fullscreen" since="2">
239+
<description summary="request that the toplevel be fullscreened">
240+
Requests that the toplevel be fullscreened on the given output. If the
241+
fullscreen state and/or the outputs the toplevel is visible on actually
242+
change, this will be indicated by the state and output_enter/leave
243+
events.
244+
245+
The output parameter is only a hint to the compositor. Also, if output
246+
is NULL, the compositor should decide which output the toplevel will be
247+
fullscreened on, if at all.
248+
</description>
249+
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
250+
</request>
251+
252+
<request name="unset_fullscreen" since="2">
253+
<description summary="request that the toplevel be unfullscreened">
254+
Requests that the toplevel be unfullscreened. If the fullscreen state
255+
actually changes, this will be indicated by the state event.
256+
</description>
257+
</request>
258+
259+
<!-- Version 3 additions -->
260+
261+
<event name="parent" since="3">
262+
<description summary="parent change">
263+
This event is emitted whenever the parent of the toplevel changes.
264+
265+
No event is emitted when the parent handle is destroyed by the client.
266+
</description>
267+
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
268+
</event>
234269
</interface>
235270
</protocol>

src/panel/widgets/window-list/toplevel.cpp

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ namespace IconProvider
3030

3131
class WayfireToplevel::impl
3232
{
33-
zwlr_foreign_toplevel_handle_v1 *handle;
33+
zwlr_foreign_toplevel_handle_v1 *handle, *parent;
34+
std::vector<zwlr_foreign_toplevel_handle_v1 *> children;
3435
uint32_t state;
3536

3637
Gtk::Button button;
@@ -48,6 +49,7 @@ class WayfireToplevel::impl
4849
impl(WayfireWindowList *window_list, zwlr_foreign_toplevel_handle_v1 *handle)
4950
{
5051
this->handle = handle;
52+
this->parent = nullptr;
5153
zwlr_foreign_toplevel_handle_v1_add_listener(handle,
5254
&toplevel_handle_v1_impl, this);
5355

@@ -235,7 +237,17 @@ class WayfireToplevel::impl
235237
return;
236238
}
237239

238-
if (!(state & WF_TOPLEVEL_STATE_ACTIVATED))
240+
bool child_activated = false;
241+
for (auto c : get_children())
242+
{
243+
if (window_list->toplevels[c]->get_state() & WF_TOPLEVEL_STATE_ACTIVATED)
244+
{
245+
child_activated = true;
246+
break;
247+
}
248+
}
249+
250+
if (!(state & WF_TOPLEVEL_STATE_ACTIVATED) && !child_activated)
239251
{
240252
auto gseat = Gdk::Display::get_default()->get_default_seat();
241253
auto seat = gdk_wayland_seat_get_wl_seat(gseat->gobj());
@@ -285,7 +297,7 @@ class WayfireToplevel::impl
285297
}
286298

287299
auto panel =
288-
WayfirePanelApp::get().panel_for_wl_output( window_list->output->wo);
300+
WayfirePanelApp::get().panel_for_wl_output(window_list->output->wo);
289301
if (!panel)
290302
return;
291303

@@ -349,6 +361,32 @@ class WayfireToplevel::impl
349361
label.set_text(shorten_title(show_chars));
350362
}
351363

364+
uint32_t get_state()
365+
{
366+
return this->state;
367+
}
368+
369+
zwlr_foreign_toplevel_handle_v1 * get_parent()
370+
{
371+
return this->parent;
372+
}
373+
374+
void set_parent(zwlr_foreign_toplevel_handle_v1 *parent)
375+
{
376+
this->parent = parent;
377+
}
378+
379+
std::vector<zwlr_foreign_toplevel_handle_v1 *>& get_children()
380+
{
381+
return this->children;
382+
}
383+
384+
void remove_button()
385+
{
386+
auto& container = window_list->box;
387+
container.remove(button);
388+
}
389+
352390
void update_menu_item_text()
353391
{
354392
if (state & WF_TOPLEVEL_STATE_MINIMIZED)
@@ -386,6 +424,10 @@ class WayfireToplevel::impl
386424

387425
void handle_output_enter(wl_output *output)
388426
{
427+
if (this->parent)
428+
{
429+
return;
430+
}
389431
auto& container = window_list->box;
390432
if (window_list->output->wo == output)
391433
{
@@ -410,6 +452,10 @@ WayfireToplevel::WayfireToplevel(WayfireWindowList *window_list,
410452
:pimpl(new WayfireToplevel::impl(window_list, handle)) { }
411453

412454
void WayfireToplevel::set_width(int pixels) { return pimpl->set_max_width(pixels); }
455+
std::vector<zwlr_foreign_toplevel_handle_v1 *>& WayfireToplevel::get_children() { return pimpl->get_children(); }
456+
zwlr_foreign_toplevel_handle_v1 * WayfireToplevel::get_parent() { return pimpl->get_parent(); }
457+
void WayfireToplevel::set_parent(zwlr_foreign_toplevel_handle_v1 *parent) { return pimpl->set_parent(parent); }
458+
uint32_t WayfireToplevel::get_state() { return pimpl->get_state(); }
413459
WayfireToplevel::~WayfireToplevel() = default;
414460

415461
using toplevel_t = zwlr_foreign_toplevel_handle_v1*;
@@ -473,13 +519,47 @@ static void handle_toplevel_done(void *data, toplevel_t)
473519
// auto impl = static_cast<WayfireToplevel::impl*> (data);
474520
}
475521

522+
static void remove_child_from_parent(WayfireToplevel::impl *impl, toplevel_t child)
523+
{
524+
auto parent = impl->get_parent();
525+
auto& parent_toplevel = impl->window_list->toplevels[parent];
526+
if (child && parent && parent_toplevel)
527+
{
528+
auto& children = parent_toplevel->get_children();
529+
children.erase(std::find(children.begin(), children.end(), child));
530+
}
531+
}
532+
476533
static void handle_toplevel_closed(void *data, toplevel_t handle)
477534
{
478535
//WayfirePanelApp::get().handle_toplevel_closed(handle);
479536
auto impl = static_cast<WayfireToplevel::impl*> (data);
537+
remove_child_from_parent(impl, handle);
480538
impl->window_list->handle_toplevel_closed(handle);
481539
}
482540

541+
static void handle_toplevel_parent(void *data, toplevel_t handle, toplevel_t parent)
542+
{
543+
auto impl = static_cast<WayfireToplevel::impl*> (data);
544+
if (!parent)
545+
{
546+
if (impl->get_parent())
547+
{
548+
impl->handle_output_enter(impl->window_list->output->wo);
549+
}
550+
remove_child_from_parent(impl, handle);
551+
impl->set_parent(parent);
552+
return;
553+
}
554+
if (impl->window_list->toplevels[parent])
555+
{
556+
auto& children = impl->window_list->toplevels[parent]->get_children();
557+
children.push_back(handle);
558+
}
559+
impl->set_parent(parent);
560+
impl->remove_button();
561+
}
562+
483563
namespace
484564
{
485565
struct zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_v1_impl = {
@@ -489,7 +569,8 @@ struct zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_v1_impl = {
489569
.output_leave = handle_toplevel_output_leave,
490570
.state = handle_toplevel_state,
491571
.done = handle_toplevel_done,
492-
.closed = handle_toplevel_closed
572+
.closed = handle_toplevel_closed,
573+
.parent = handle_toplevel_parent
493574
};
494575
}
495576

src/panel/widgets/window-list/toplevel.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ class WayfireToplevel
2626
public:
2727
WayfireToplevel(WayfireWindowList *window_list, zwlr_foreign_toplevel_handle_v1 *handle);
2828

29+
uint32_t get_state();
2930
void set_width(int pixels);
31+
zwlr_foreign_toplevel_handle_v1 * get_parent();
32+
void set_parent(zwlr_foreign_toplevel_handle_v1 *);
33+
std::vector<zwlr_foreign_toplevel_handle_v1 *>& get_children();
3034
~WayfireToplevel();
3135

3236
class impl;

src/panel/widgets/window-list/window-list.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static void registry_add_object(void *data, wl_registry *registry, uint32_t name
143143
auto zwlr_toplevel_manager = (zwlr_foreign_toplevel_manager_v1*)
144144
wl_registry_bind(registry, name,
145145
&zwlr_foreign_toplevel_manager_v1_interface,
146-
std::min(version, 1u));
146+
std::min(version, 3u));
147147

148148
window_list->handle_toplevel_manager(zwlr_toplevel_manager);
149149
}
@@ -192,7 +192,10 @@ void WayfireWindowList::set_button_width(int width)
192192
{
193193
std::cout << "set width " << width << std::endl;
194194
for (auto& toplevel : toplevels)
195-
toplevel.second->set_width(width);
195+
{
196+
if (toplevel.second)
197+
toplevel.second->set_width(width);
198+
}
196199
}
197200

198201
int WayfireWindowList::get_default_button_width()

0 commit comments

Comments
 (0)