Commit graph

264 commits

Author SHA1 Message Date
Maik Broemme
8fdf375af3
window-switcher: add order parameter to allow stable window list ordering
Some checks failed
labwc.github.io / notify (push) Has been cancelled
Add a new configuration option to control the window switcher traversal order.

`order="focus"` cycling is convenient for quick toggling, but some users - me as well -
prefer a stable taskbar-like order which can now be achieved with `order="age"`.
2025-12-08 18:54:23 +01:00
John Lindgren
d748dc78bc xwayland: flush XCB connection to mitigate race between Raise and input
Some checks are pending
labwc.github.io / notify (push) Waiting to run
2025-12-02 19:50:03 +01:00
John Lindgren
d20d5675f5 xwayland: don't send _NET_WM_PING to new windows
No one remembers why we were doing this, and we do not handle the
ping_timeout event, so it seems pointless. Also it appears to confuse
some older X clients.
2025-12-02 09:21:42 +01:00
John Lindgren
27aa8173f3 view: move view_moved() out of view_impl_apply_geometry() 2025-12-02 14:57:41 +09:00
tokyo4j
acb3da7903 cursor: generalize seat->pressed
This commit moduralize seat_{set,reset}_pressed() into
cursor_context_save() so that we can also have seat->hovered later.
2025-11-30 20:55:54 +09:00
John Lindgren
35b3980a5b xwayland: hide content tree at re-map if shaded 2025-11-27 01:26:55 -05:00
John Lindgren
b9da216bde xwayland: associate/dissociate/map/unmap cleanups
- connect/disconnect map handlers in set_surface()
- call set_surface() at time of associate/dissociate

This separates the concepts of "associate" and "map" more clearly.

It's no longer necessary to listen for wlr_surface "destroy" event,
because dissociate is always received first.

Also, view->content_tree is now destroyed and set to NULL at unmap.
Previously, we relied on wlr_scene to destroy it automatically when
the surface was destroyed, but kept a potentially dangling pointer in
view->content_tree until next map. Similar change for unmanaged.

v2: comment updates
2025-11-27 01:26:55 -05:00
tokyo4j
4b0903cfa9 view: deduplicate foreign-toplevel creation code 2025-11-27 01:26:55 -05:00
tokyo4j
3c0e010c58 Remove view_impl->map and view_impl->unmap
jlindgren: data parameter to handle_unmap() is NULL
2025-11-27 01:26:55 -05:00
John Lindgren
b5e2eb216e view: separate (un)minimize and (un)map logic
Map/unmap logic is currently re-used for minimize/unminimize, but lots
of it doesn't actually apply in that case. This is both confusing and
creates some extra complexity, such as:

 - extra "client_request" parameter to unmap(), in which case it has to
   still do some cleanup even if view->mapped is already false

 - various "view->mapped || view->minimized" checks when we really just
   mean "is the view mapped"

To clean this all up, let's put the logic that really is common into
a new view_update_visiblity() function, and stop using map/unmap for
minimize/unminimize.

Note that this changes the meaning of "view->mapped", which used to
mean "mapped and not minimized" but now really just means "mapped".
I left some "view->mapped" conditions as-is (rather than changing to
"view->mapped && !view->minimized") where it seemed to make sense.

v2: add view_update_visibility() as suggested by tokyo4j
2025-11-21 14:01:48 +09:00
John Lindgren
8ced055cb9 xwayland: remove obsolete (since wlroots 0.17) NULL check
Since d7dc6e01b4 ("Chase wlroots: Unified mapping"), the map event
is emitted by the wlr_surface itself, thus it cannot be NULL.

Change the "if" to an "assert" accordingly.
2025-11-15 12:19:31 +01:00
John Lindgren
5543affe35 view: factor out view_impl_init_foreign_toplevel() 2025-11-13 00:07:11 +01:00
John Lindgren
79fbb611e0 view: less hacky support for minimize-before-map
The previous "minimal fix" (5148c2aa31) worked but was a bit of a
hack, as it basically un-minimized and then immediately minimized the
view again at map. It's not actually too difficult to make the map
handlers aware of minimized views, eliminating the need for the hack.

Note: this depends on the previous commit ("xwayland: connect commit
and surface_destroy handlers together") otherwise the xwayland map
handler registers the commit handler twice, leading to a crash.
2025-11-09 18:27:39 +00:00
John Lindgren
b6f7bacdde xwayland: connect commit and surface_destroy handlers together
Factor out set_surface() which consolidates connecting/disconnecting
the wlr_surface event listeners in one place.

In theory, this means we can receive commit events for minimized views.
However, with a test app that resizes itself, I didn't see any change,
i.e. the commits still don't come through until un-minimize. It's
possible they are being filtered at wlroots or protocol level.

Also remove an old, semi-related TODO from view.c.
2025-11-09 18:27:39 +00:00
tokyo4j
babd7af8f8 view: store title/app_id in view
This simplifies our codes and eliminates duplicated
`view.events.new_{title,app_id}` events. This should not change any
behaviors.
2025-10-14 02:27:13 +09:00
Johan Malm
950c634cea Privatize xwayland_surface_from_view() 2025-09-29 20:22:46 +01:00
John Lindgren
d2ce31fcc9 tree-wide: use forward declarations for wlr types 2025-09-07 19:34:30 +09:00
John Lindgren
f129571779 ssd: unify struct ssd_part with struct node_descriptor
struct ssd_part and struct node_descriptor seem to have essentially the
same purpose: tag a wlr_scene_node with some extra data indicating what
we're using it for.

Also, as with enum ssd_part_type (now lab_node_type), ssd_part is used
for several types of nodes that are not part of SSD.

So instead of the current chaining (node_descriptor -> ssd_part), let's
flatten/unify the two structs.

In detail:

- First, merge node_descriptor_type into lab_node_type.
- Add a separate view pointer in node_descriptor, since in the case of
  SSD buttons we need separate view and button data pointers.
- Rename ssd_part_button to simply ssd_button. It no longer contains
  an ssd_part as base.
- Add node_try_ssd_button_from_node() which replaces
  node_ssd_part_from_node() + button_try_from_ssd_part().
- Factor out ssd_button_free() to be called in node descriptor destroy.
- Finally, get_cursor_context() needs a little reorganization to handle
  the unified structs.

Overall, this simplifies the code a bit, and in my opinion makes it
easier to understand. No functional change intended.
2025-09-06 16:00:20 -04:00
John Lindgren
1188534876 common: add node-type.c/h (renaming ssd_part_type to lab_node_type)
ssd_part_type contains several node types that are not actually part of
server-side decorations (ROOT, MENU, OSD, etc.)

Rename it accordingly and move it to a common location, along with some
related conversion/comparison functions.
2025-09-06 16:00:20 -04:00
tokyo4j
e6b5d91b63 view: let view_set_fallback_natural_geometry() return wlr_box 2025-09-01 20:16:37 +01:00
tokyo4j
164b17c279 view: use fixed default window width
Now it's not very reasonable to determine the default window width based
on the titlebar geometry, as the titlebar can be shrunk to 1px.

Let's use the fixed value of 100px for simplification.
2025-09-01 20:13:00 +01:00
John Lindgren
ef766d16f0 common: flesh out enum lab_edge and prefer over wlr_edges/wlr_direction
I like the new common/edge.h. I don't like how inconsistently we use it.

Current situation:

 - enum wlr_edges and wlr_direction are designed to be used as bitset,
   and are defined compatibly

 - enum lab_edge is *also* designed to be used as bitset, but
   incompatible with the others (LEFT/RIGHT come before UP/DOWN)

 - we use an inconsistent mix of all three *AND* uint32_t (usually with
   the WLR_EDGE constants rather than the LAB_EDGE constants), and
   convert between them on an ad-hoc basis, sometimes implicitly

Let's clean this up:

 - reorder enum lab_edge to be compatible with the two wlr enums
   (check this by static_assert)

 - use TOP/BOTTOM naming rather than UP/DOWN (matches wlr_edges)

 - add constants for the remaining possible combinations of the 4 edges

 - use lab_edge for all internal edge/direction fields, consistently

 - add lab_edge_is_cardinal() as a sanity check before casting to
   enum wlr_direction, and then eliminate all of direction.c/h

Instead of "enum wlr_edges direction", we now have
"enum lab_edge direction" which is not that much better. At least we
are now clear that we're overloading one enum with two meanings.
2025-08-26 20:36:43 -04:00
John Lindgren
9d49d19cd2 include: add config/types.h 2025-08-21 16:55:25 +09:00
John Lindgren
02df0a15d7 foreign-toplevel: simplify and fully separate ext-foreign/wlr-foreign
Currently, the dependencies between foreign-toplevel[-internal],
ext-foreign, and wlr-foreign are cyclical and a bit complex.

I suggest we reorganize it into a simpler hierarchy:

  foreign-toplevel/
    -> foreign.c/h
      -> (depends on) ext-foreign.c/h
      -> (depends on) wlr-foreign.c/h

The refactored code is smaller and (IMO) easier to follow.

In detail:

- Add include/foreign-toplevel folder mirroring src/foreign-toplevel
- Split foreign-toplevel-internal.h to ext-foreign.h and wlr-foreign.h
- Eliminate ext-/wlr-foreign.c -> foreign.c reverse dependencies
  (including internal signals and foreign_request* functions)
- Make struct foreign_toplevel private to foreign.c

Lightly tested with qmpanel (which uses wlr-foreign-toplevel).

v2: reorder foreign-toplevel internal API funcs
2025-08-07 23:27:04 -04:00
John Lindgren
e1475a1e47 include: reduce global includes in labwc.h 2025-07-30 21:04:31 +01:00
John Lindgren
e21fc065c4 include: split output.h from labwc.h 2025-07-30 21:04:31 +01:00
John Lindgren
31d42b50e2 src: include primary header first
This is a common practice in C projects, which simply enforces that
each header must compile cleanly without implicit dependencies on
other headers (see also the previous commit).
2025-07-29 21:51:56 +01:00
tokyo4j
0d9384de74 style: remove newlines after wl_list_for_each_reverse() 2025-07-27 08:26:39 +09:00
John Lindgren
bb2d34a5c1 xwayland: fix swapped width/height in _NET_WM_ICON stride calculation
Probably slipped through since most window icons are square anyway.
2025-07-13 03:51:40 +02:00
Consolatis
a8df2487b2 xwayland: support _NET_WM_ICON 2025-06-18 14:31:05 +09:00
John Lindgren
9782ffa868 desktop: give focus to a modal dialog rather than its parent
Fixes: #2722
2025-06-13 18:40:29 +01:00
John Lindgren
5a1466d355 xwayland: handle rare case of focus_in event occurring before map
This fixes a timing-dependent issue where the CLion main window was
sometimes not correctly focused at startup.
2025-06-12 20:33:25 +01:00
John Lindgren
8fb2ecefcb xwayland: always offer focus in Globally Active case
In 9e3785f8cd, a heuristic was added to assume that NORMAL and DIALOG
window types were always focusable. (This was before we had the "offer
focus" mechanism in place.)

However, we should still call wlr_xwayland_surface_offer_focus() for
these views, in case they actually don't want focus. (This is uncommon
but has recently been seen with WeChat popups, which have both NORMAL
and UTILITY type.)

To make this possible, refine view_wants_focus() to return either
LIKELY or UNLIKELY for Globally Active input windows. This decouples
the question of "should we try to focus this view" from the actual
mechanism used to do so.
2025-06-10 11:03:54 -04:00
Consolatis
4d79f0057f Ensure the view signals are initialized early
This prevents a crash observed by the scaled-icon-buffer listening
to the `view->events.set_icons` signal before it is initialized.
For this to happen, the application needs to use the kde decoration
protocol and set it on the xdg_surface before creating the xdg_toplevel.

Fixes: #2798
2025-06-07 05:03:57 +02:00
John Lindgren
fd5031731e xwayland: use wlr_xwayland_surface_has_window_type()
This eliminates a bit of logic, including an extra XWayland connection.

See also:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4553
2025-05-22 23:09:41 +01:00
John Lindgren
c00baa1651 xwayland: use wlr_xwayland_surface_offer_focus()
Offer focus by sending WM_TAKE_FOCUS to a client window supporting it.
The client may accept or ignore the offer. If it accepts, the surface will
emit a focus_in signal notifying the compositor that it has received focus.
The compositor should then call wlr_xwayland_surface_activate(surface, true).

This is a more compatible method of giving focus to windows using the
Globally Active input model (see wlr_xwayland_icccm_input_model()) than
calling wlr_xwayland_surface_activate() unconditionally, since there is no
reliable way to know in advance whether these windows want to be focused.

v2: add caution not to use view_offer_focus() directly
v3: remove obsolete comment
2025-05-21 20:30:19 +02:00
tokyo4j
261126fcd0 chase wlroots: let scene restack xwayland surfaces (MR 4756)
Ref: 1133bc15ceb2c2bcb6df692acda6bfa39a292ab5
("Transparently restack xwayland surfaces")

In addition, MR 4772 makes sure the hidden windows are stacked at the
bottom, just like what we did with XWAYLAND_VIEW_HIDDEN.
2025-05-21 06:36:08 +01:00
Consolatis
1eaba4af33 chase wlroots: xwayland separate maximized axis MR 4670
Ref: ceb4fcedca30d323a05836b0872bfe773a047ccc
("xwm: expose individual axis for _set_maximized()")
2025-05-21 06:36:08 +01:00
Consolatis
a617accfd8 chase wlroots: _wants_focus and input_model renames MR 2434
Ref: d3b7e040af46ab03114d5a40e9ed0c7c6aff15be
("wlr_xwayland_surface: fix prefix of two functions")
2025-05-21 06:36:08 +01:00
Consolatis
568bc71ca2 xwayland.c: support both axis for client side maximize requests 2025-05-18 05:03:06 +02:00
tokyo4j
81204b0537 xwayland: notify correct window stacking order to xwayland
Before this commit, when a normal window is raised, xwayland thought it's
above always-on-top (AOT) windows even though it's actually below AOT
windows in the scene. This means mouse scroll events may be unexpectedly
sent to normal windows below AOT windows even when the cursor is hovering
over a AOT window.

So this commit fixes it by notifying the correct stacking order (where AOT
windows are placed above normal windows) to xwayland every time the
stacking order is updated.

Other benefits of this commit are:
- It makes the code more readable and predictable by aggregating logic
  about stacking order management in xwayland (e.g. shaded windows or
  windows in other workspaces should be notified to xwayland as being
  placed at the bottom).
- As server->last_raised_view is removed in the previous commit, we were
  notifying the stacking order to xwayland every time a window with dialog
  windows is clicked (not when clicking a topmost window without dialogs,
  due to some optimization in wlroots). This commit fixes this by caching
  the window stacking order in xwayland_view->stacking_order and notifying
  it to xwayland only when it's updated.
2025-04-01 16:48:40 +09:00
Consolatis
9e6aaa689a project wide: clean up event listeners on shutdown
This ensures all event listeners are removed before the emitting
wlroots object is being destroyed. This will be enforced with asserts
in wlroots 0.19 but there is no reason to not do it right now either.

This change in wlroots 0.19 is implemented via commit
8f56f7ca43257cc05c7c4eb57a0f541e05cf9a79
"Assert (almost all) signals have no attached listeners on destroy"
2025-03-13 17:33:51 +09:00
tokyo4j
270b45da88 desktop: harden window stacking order while window switching
This commit moves the check against server->input_mode from the callers
of desktop_focus_view() into desktop_focus_view() itself. This
eliminates code duplications and makes it harder to mess up the window
stacking order while window switching.

I also added the same check in view_minimize() so that minimize requests
from panels never messes up the window stacking order (I think only this
should be described in the release note).
2025-03-09 20:41:26 +00:00
tokyo4j
4b7c502ace view: replace content_node with content_tree 2025-01-22 18:02:54 +01:00
Johan Malm
023427b4f4 view: fix NULL string_prop crash
...when app_id is NULL.

Make sure view_get_string_prop() never returns NULL because it is so easy
to misuse. Same for the respective xwayland/xdg impl methods in case
anyone decides to (incorrectly) call them directly in future.

Fixes: #2453
2024-12-29 13:06:30 +00:00
tokyo4j
5d3ce3e190 Check input_mode to see whether window switcher is active or not
...rather than "if (server->osd_state.cycle_view){..}".
2024-12-28 21:28:22 +00:00
tokyo4j
daae379433 view: s/scene_node/content_node/ 2024-12-14 12:03:58 +09:00
Consolatis
2a825008c6 foreign-toplevel: create generic abstraction 2024-11-09 20:06:19 +00:00
Consolatis
5e1f91c9d1 view: add state change signals 2024-11-09 20:06:19 +00:00
John Lindgren
977d561695 icon-loader: fix a few more missing icons
By:
- stripping extensions from relative icon filenames (for example,
  gdmap.desktop has "Icon=gdmap_icon.png")
- using the WM_CLASS "instance" rather than "class" string, which
  is usually the same but lowercase
2024-10-05 21:01:55 +01:00