Commit Graph

16 Commits

Author SHA1 Message Date
Window Maker b94bc2ce95 WPrefs: drop SIGUSR2, rely on inotify for defaults reload
SIGUSR2 is fundamentally unsafe in a multi-threaded compositor: library
threads (pango fontconfig) created after pthread_sigmask receive the
signal and crash. The Wayland event loop already has inotify watching
the defaults directory, so file changes are detected automatically
without any explicit signaling.

The early pthread_sigmask(SIG_BLOCK, SIGUSR2) is retained as a safety
measure to prevent stray SIGUSR2 from terminating the compositor.
2026-05-25 12:02:26 +02:00
Window Maker 9dee4f7a65 WPrefs: fix SIGUSR2 targeting wmaker instead of parent shell
The previous getppid() approach sent SIGUSR2 to the terminal process
(foot) rather than wmaker, killing the shell. Now wmaker exports
WMAKER_PID at startup and wl_send_wm_command reads it to signal the
correct process.
2026-05-25 11:55:14 +02:00
Window Maker 35226c8588 WPrefs: send SIGUSR2 to wmaker after saving settings
The Wayland event backend stub for send_wm_command was a no-op, so
WPrefs settings changes never triggered a reread in the running wmaker.
Now sends SIGUSR2 to the parent process (wmaker) on "Reconfigure",
causing wDefaultsCheckDomains to run and apply changes immediately.
2026-05-25 11:51:25 +02:00
Window Maker ffc4806f0b WINGs: implement keysym/keycode/modifier stubs and window_set_title
- wl_keysym_to_string: xkb_keysym_get_name
- wl_keysym_to_keycode: iterate keymap to find keycode
- wl_keycode_to_keysym: xkb_keymap_key_get_syms_by_level
- wl_keysym_convert_case: xkb_keysym_to_lower/upper
- wl_get_modifier_keysyms: standard XKB_KEY_* for 8 modifiers
- wl_window_set_title: calls xdg_toplevel_set_title
- W_WLClientGetKeymap accessor for xkb_keymap
2026-05-24 22:25:36 +02:00
Window Maker b52ca0747c WINGs: commit all mapped toplevels on every event loop flush
Widgets that paint directly to their view backing (fill_rect,
draw_line, W_DrawRelief, W_PaintText) without going through the
DOUBLE_BUFFER pixmap_copy path never triggered a surface commit.
The painted content stayed in the pixman buffer but was never
submitted to the compositor — making popup menus, radio buttons,
text fields, sliders, and other controls appear empty/stale.

Fix: W_WLClientCommitAllToplevels() iterates all mapped toplevels
and commits their surfaces. Called from wl_flush() which runs once
per event loop iteration (in waitForEvent). This ensures any
direct-paint operations become visible on the next frame regardless
of which render path was used.
2026-05-24 22:17:17 +02:00
Window Maker db915281e0 WINGs/wevent_wl: implement translate_coordinates and get_window_geometry
Both were no-op stubs returning 0/False.  Editmenu uses these to
compute the original screen position of an item before drag-and-drop,
then animates the item back to that position via slideWindow on
revert.  With both returning 0, the slide animation moved popups
from where they were to (0, 0) instead of back to their origin —
producing the 'menus moving on their own' effect.

translate_coordinates: walk up from src view accumulating pos.x/y
to compute the position relative to the toplevel.

get_window_geometry: return the view's pos/size directly.
2026-05-24 19:27:33 +02:00
Window Maker 60348da411 Implement wmaker-popup-v1 Wayland protocol for client-driven popup positioning
Standard xdg_shell does not allow Wayland clients to position toplevels —
the compositor decides placement.  WINGs UI patterns require client-driven
positioning (e.g., a dropdown popup must appear directly below its trigger
button; menu editor items must be placed by the client at specific screen
coordinates).

This protocol lets the client wrap an xdg_toplevel with a wmaker_popup
object and call set_position(x, y) before the surface is mapped.  The
compositor honours the requested position when the surface becomes visible
and on subsequent set_position calls.

Files:
- protocols/wmaker-popup-v1.xml: protocol definition
- src/Makefile.am, src/Makefile: server-protocol.h + protocol.c generation
- WINGs/Makefile.am, WINGs/Makefile: client-protocol.h + protocol.c generation
- src/backend/wayland/wl_backend.c: wmaker_popup_manager global, get_popup
  handler that wraps an xdg_toplevel; set_position handler that updates
  view->popup_x/y and calls wmaker_popup_apply to move the frame_buf
  scene tree.  Apply runs at toplevel_map time too for pre-map positions.
- WINGs/wclient_wl.c: bind manager in registry, wrap popup toplevels with
  wmaker_popup, expose W_WLClientPopupSetPosition.
- WINGs/wview_wl.c: wl_move calls W_WLClientPopupSetPosition for popup
  toplevels so WMMoveWidget propagates to the compositor.
- WINGs/wevent_wl.c: wl_move_window also routes to popup positioning.
2026-05-24 18:27:55 +02:00
Window Maker 04e6b348b2 Implement popup-style toplevels for menu editor on Wayland
The WPrefs menu editor creates standalone draggable windows for each
menu item via W_CreateTopView. On X11 these are override-redirect
windows. On Wayland they were becoming framed XDG toplevels with
taskbar entries, cluttering the desktop with phantom 'WINGs...' tabs.

Implementation:
1. New W_View flags.popup field, set by editmenu's standalone mode
2. wclient_wl: when realizing a popup view, set xdg_toplevel app_id
   to 'wings-popup' as a hint to the compositor
3. wmaker compositor: detect 'wings-popup' app_id in toplevel_map,
   set borderless + skip-taskbar + skip-switchpanel flags, then call
   wWindowConfigureBorders to rebuild the frame without decorations
4. New W_EventBackend->window_begin_move vtable method:
   - X11: returns False (caller runs manual drag loop)
   - Wayland: calls xdg_toplevel_move, returns True (compositor drives drag)
5. editmenu's dragMenu calls window_begin_move first; on Wayland the
   compositor handles the entire drag, so the manual loop is skipped
2026-05-24 17:58:58 +02:00
Window Maker 8119bfe098 WPrefs.app: zero X11 deps, zero #ifdef USE_X11_BACKEND
Complete architectural separation: all WPrefs.app panel code is now
backend-neutral. No X11 calls, no X11 types, no X11 includes, no
backend-specific #ifdef guards in shared sources.

New W_EventBackend vtable methods (implemented in X11, stubbed in WL):
  - grab_keyboard / ungrab_keyboard / allow_events
  - grab_pointer / ungrab_pointer / query_pointer
  - get_window_geometry / move_window / translate_coordinates
  - get_root_window / query_tree
  - get_pointer_control / set_pointer_control
  - modifier_from_key / get_modifier_keysyms
  - keysym_to_string / keysym_to_keycode / keycode_to_keysym
  - keysym_convert_case
  - send_wm_command
  - set_window_hints / set_window_property_string / set_window_property_data
  - recolor_cursor
  - set_error_handler / restore_error_handler

Panel changes:
  - xmodifier.c: thin wrapper calling eventBackend->modifier_from_key()
  - main.c: X11 locale init removed (belongs in backend screen_init)
  - WPrefs.c: eventBackend->send_wm_command("Reconfigure")
  - MouseSettings.c: vtable for pointer control + modifier keysyms
  - KeyboardShortcuts.c: vtable for grab/keysym/modifier ops
  - Menu.c: RImage crosshair icon, vtable keyboard grab
  - editmenu.c: vtable for all window/pointer/property ops

Verified: nm audit shows zero X11 symbol refs in WPrefs .o files.
grep shows zero #ifdef USE_X11_BACKEND in WPrefs.app/.
2026-05-24 14:04:14 +02:00
Window Maker ef06f5ad8e wings: phases δ + ε — drop X11/Xlib.h from public WINGs headers
Major architectural milestone: WINGs Wayland-only files now have ZERO
transitive X11 header dependency at the preprocessor level (verified by
gcc -E grep: 0 mentions of X11/Xlib.h after preprocessing).

Changes:

  1. WUtil.h, WINGs.h: stop including <X11/Xlib.h>.  wnative.h provides
     forward declarations for Display, GC, XftDraw, XftFont; opaque
     pointer-only typedefs that don't conflict with Xlib.h's actual
     definitions when the X11 backend later includes it.

  2. WINGsP.h.in: stop including <X11/Xlib.h>, <X11/Xutil.h>.  Drop or
     re-route every X11-typed prototype:
       - W_HandleDNDClientMessage / W_DragSourceStateHandler /
         W_DragDestinationStoreEnterMsgInfo / etc.
         → moved to new private header WINGs/WINGsX11.h
       - W_HandleSelectionEvent → moved
       - W_LookupString / W_KeycodeToKeysym → moved
       - W_DndState typedef → moved (renamed to W_X11DndState)
       - XClientMessageEvent / XEvent / XKeyPressedEvent in prototypes
         → use void * in shared protos, cast in WINGsX11.h

  3. W_View struct: replaces XSetWindowAttributes by-value field with a
     small backend-neutral 'attribs' struct holding only the fields
     wmaker/WPrefs actually use (background_pixmap, background_pixel,
     border_pixel, colormap, cursor, override_redirect, save_under,
     event_mask, do_not_propagate_mask).  The X11 view backend
     translates to XSetWindowAttributes when calling XCreateWindow.
     XIC xic field replaced with void *xic.

  4. W_Color struct: replaces XColor by-value with a same-layout
     anonymous struct (pixel/red/green/blue/flags/pad).  X11 backend
     uses memcpy to populate from XColor.

  5. WINGs/WINGsX11.h (new): private header for X11 backend.  Includes
     <X11/Xlib.h>, declares X11-typed internal prototypes used by drag*,
     selection, IME, x11_backend, KeyboardShortcuts.  Required by every
     *_x11.c file plus a handful of cross-component callers
     (KeyboardShortcuts.c, MouseSettings.c, xmodifier.c, wmiv.c,
     x11_backend.c).

  6. wraster.h.in: gain a WRASTER_NO_XLIB compile-time switch.  When
     defined the header skips <X11/Xlib.h> and provides forward decls
     for Display/Visual/XImage/GC/XftFont/etc.  All Wayland-only WINGs
     files (wclient_wl.c, w*_wl.c) define WRASTER_NO_XLIB on line 1.

  7. wfont.c: adds W_ParseXLFDToFcPattern (a hand-written XLFD parser)
     replacing XftXlfdParse.  Removes <X11/Xft/Xft.h> include from the
     shared font dispatcher (and from wfontpanel.c too).

Verification:

  $ for f in WINGs/.libs/{*_wl.o,wclient_wl.o}; do
        nm $f | awk '$1=="U"{print $2}' | grep -cE '^X[A-Z][a-z]'
    done
  0 for every Wayland file

  $ for f in WINGs/.libs/*.o; do
        case $f in *_x11.o|*_wl.o|wclient_wl.o) continue;; esac
        c=$(nm $f | awk '$1=="U"{print $2}' | grep -cE '^X[A-Z][a-z]')
        [ $c -gt 0 ] && echo "$c $f"
    done
  (empty — no shared file leaks an X11 symbol either)

  $ gcc -E ... wclient_wl.c | grep -c X11/Xlib.h
  0 (no transitive Xlib include)

The library still pulls libX11 through the *_x11.c files when those are
linked in.  A future configure flag --disable-x11-backend will exclude
*_x11.c entirely; at that point libWINGs will be a pure-Wayland library
with zero libX11 dependency.
2026-05-24 11:37:18 +02:00
Window Maker 82e3c3b65d wings: phase α.2 — rename X11 event masks to WM_EVMASK_*
Sed pass.  KeyPressMask, KeyReleaseMask, ButtonPressMask,
ButtonReleaseMask, EnterWindowMask, LeaveWindowMask,
PointerMotionMask, PointerMotionHintMask, Button{1..5}MotionMask,
ButtonMotionMask, KeymapStateMask, ExposureMask,
VisibilityChangeMask, StructureNotifyMask, ResizeRedirectMask,
SubstructureNotifyMask, SubstructureRedirectMask, FocusChangeMask,
PropertyChangeMask, ColormapChangeMask all renamed to the
corresponding WM_EVMASK_* names defined in wnative.h.

Numeric values still match the X11 layout, so wevent_x11.c's
matching tables and any code that masks bits keep working
unchanged.  Build clean across WINGs/, src/, WPrefs.app/.
2026-05-24 10:43:23 +02:00
Window Maker 15bec04b1b fix: eliminate use-after-free crash on modal dialog close
- wevent_wl.c: W_IsValidView() validates _view_target against view_table
     at fetch boundary (wl_fetch, wl_check_mask, wl_check_typed_window);
     nulls target before returning event if view was destroyed
   - wevent_wl.c: W_WL_InvalidateView() nulls queue entries at destroy time
   - wview.c: set view->screen=NULL before wfree(view)
   - wevent.c: defense-in-depth: check !view->screen || alreadyDead before use
2026-05-17 19:16:32 +02:00
Levi Neely 95b0b8ee7c WINGs/wevent: remove _x11_raw from WMHandleEvent dispatch path
WMHandleEvent is the middle layer — it must not contain any
backend-specific code. Move view lookup to _view_target field
set by each event backend during fetch. Move XRefreshKeyboardMapping
and XFilterEvent into x11_fetch. Selection and DND handling removed
from middle layer (handled by extraEventHandler in the WM layer).

The _x11_raw field remains in WMEvent for now (used by src/event.c
and other WM-layer code that still needs the raw XEvent), but the
middle layer no longer touches it.
2026-05-14 20:24:05 +02:00
Levi Neely 8f0ec30759 Fix keyboard input: don't forward keys to seat without focused surface
wlr_seat_keyboard_notify_key was being called unconditionally, which
caused re-entrancy that consumed WINGs events from the queue before
the modal loop could fetch them. Now only forwards to the seat when
there's an actual focused client surface.

Also use 16ms timeout in wl_flush so keyboard events from the nested
compositor are actually received during modal loop dispatch.
2026-05-13 22:48:13 +02:00
Levi Neely d93f4935ca Fix input dispatch: custom event loop + modal menu support
The deadlock: frame_timer_cb called WMHandleEvent which entered
menuMouseDown's modal WMMaskEvent loop. That blocked inside
wl_event_loop_dispatch (reentrant), preventing new events.

Fix:
1. Replace wl_display_run() with custom loop that drains WINGs
   events BETWEEN wl_event_loop_dispatch calls (not inside timer)
2. Make WINGs wl_flush() pump wlroots (call dispatch_fn) so
   WMMaskEvent modal loops get new events without reentrancy
3. Fix wBalloonHide NULL dereference (scr->balloon not allocated)
4. Remove XEvent dependency from wSelectWindows (takes x,y now)
5. Remove debug traces

Right-click on background now opens the root menu.
2026-05-13 16:22:13 +02:00
Levi Neely 9b2448dd7f WIP: Wayland backend - fix atoms, OR surface compositing, frame/window ops
Key changes in wl_backend.c:
- wl_atom_intern: call XInternAtom on XWayland display (was returning 0)
- Add wl_or_view struct to track override_redirect XWayland surfaces
- handle_xwayland_new_surface: composite OR surfaces via scene graph
- frame_create_toplevel/child: create real X11 windows on XWayland
- frame_destroy/configure: delegate to Xlib
- window_map/unmap/move/resize: fall through to Xlib for frame windows
- stacking_raise/lower: update scene graph + Xlib fallback
- event_flush/sync: call XFlush/XSync on XWayland display
- window_set_border/border_width/clear: delegate to Xlib
- window_get_rect: query XWayland geometry for non-toplevel windows

Note: frame creation via XWayland is a temporary bridge. The correct
architectural approach is native scene-buffer rendering with pixman.
2026-05-13 07:05:22 +02:00