diff options
author | Josh Rahm <rahm@google.com> | 2024-02-22 16:07:54 -0700 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2024-02-22 16:08:38 -0700 |
commit | 320d4a87447491abd1fa0cfa898bd6b5ae73dee9 (patch) | |
tree | 923347ae3fbcef1b3fe20ca4f6fca69fda3ff05b | |
parent | 0724c6d9cd77d83bd113204bdec5ac23491c35d7 (diff) | |
download | wetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.tar.gz wetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.tar.bz2 wetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.zip |
better surface handling
-rw-r--r-- | harness/include/plugin.h | 7 | ||||
-rw-r--r-- | harness/include/plugin_types.h | 9 | ||||
-rw-r--r-- | harness/src/wl.c | 12 | ||||
-rw-r--r-- | harness/src/wl.h | 95 | ||||
-rw-r--r-- | harness/tools/genintf.pl | 2 | ||||
-rw-r--r-- | src/Wetterhorn/Core.hs | 9 | ||||
-rw-r--r-- | src/Wetterhorn/FFI.hs | 42 | ||||
-rw-r--r-- | src/Wetterhorn/WlRoots.hs | 33 |
8 files changed, 171 insertions, 38 deletions
diff --git a/harness/include/plugin.h b/harness/include/plugin.h index 46e833a..cc18158 100644 --- a/harness/include/plugin.h +++ b/harness/include/plugin.h @@ -9,6 +9,7 @@ #include <wlr/types/wlr_input_device.h> #include <wlr/types/wlr_keyboard.h> +#include "plugin_types.h" #include <foreign_intf.h> /* @@ -31,7 +32,6 @@ typedef void *dlhandle_t; /* Opaque state for a plugin. Not to be touched by the harness (not that it * really can be.) */ -typedef void *opqst_t; struct PLUGIN; /* This structure represents an action requested by the plugin for the harness. @@ -146,9 +146,8 @@ typedef struct PLUGIN { /* * Handles a surface being mapped, unmapped or destroyed. */ - EXPORT(opqst_t (*plugin_handle_surface_map)(void *surface, opqst_t)); - EXPORT(opqst_t (*plugin_handle_surface_unmap)(void *surface, opqst_t)); - EXPORT(opqst_t (*plugin_handle_surface_destroy)(void *surface, opqst_t)); + EXPORT(opqst_t (*plugin_handle_surface)(void *surface, surface_event_t event, + opqst_t)); /* List of requested actions by the plugin. Right now there is a maximum of 8 * allowed at one time. That should be plenty. The actions should be flushed diff --git a/harness/include/plugin_types.h b/harness/include/plugin_types.h new file mode 100644 index 0000000..df1eab5 --- /dev/null +++ b/harness/include/plugin_types.h @@ -0,0 +1,9 @@ +#pragma once + +typedef void *opqst_t; + +typedef enum { + SURFACE_MAP = 0, + SURFACE_UNMAP, + SURFACE_DELETE, +} surface_event_t; diff --git a/harness/src/wl.c b/harness/src/wl.c index bed98b4..2bbef59 100644 --- a/harness/src/wl.c +++ b/harness/src/wl.c @@ -627,8 +627,8 @@ static void xdg_surface_map(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ struct tinywl_view *view = wl_container_of(listener, view, map); - plugin_call_update_state(view->server->plugin, plugin_handle_surface_map, - data); + plugin_call_update_state(view->server->plugin, plugin_handle_surface, data, + SURFACE_MAP); view->mapped = true; focus_view(view, view->xdg_surface->surface); } @@ -637,8 +637,8 @@ static void xdg_surface_unmap(struct wl_listener *listener, void *data) { /* Called when the surface is unmapped, and should no longer be shown. */ struct tinywl_view *view = wl_container_of(listener, view, unmap); - plugin_call_update_state(view->server->plugin, plugin_handle_surface_unmap, - data); + plugin_call_update_state(view->server->plugin, plugin_handle_surface, data, + SURFACE_UNMAP); view->mapped = false; } @@ -646,8 +646,8 @@ static void xdg_surface_destroy(struct wl_listener *listener, void *data) { /* Called when the surface is destroyed and should never be shown again. */ struct tinywl_view *view = wl_container_of(listener, view, destroy); - plugin_call_update_state(view->server->plugin, plugin_handle_surface_destroy, - data); + plugin_call_update_state(view->server->plugin, plugin_handle_surface, data, + SURFACE_DELETE); wl_list_remove(&view->link); free(view); } diff --git a/harness/src/wl.h b/harness/src/wl.h new file mode 100644 index 0000000..f24dc1b --- /dev/null +++ b/harness/src/wl.h @@ -0,0 +1,95 @@ +#pragma once + +#include "plugin.h" +#include <getopt.h> +#include <stdbool.h> +#include <unistd.h> +#include <wayland-server-core.h> +#include <wlr/backend.h> +#include <wlr/render/wlr_renderer.h> +#include <wlr/types/wlr_compositor.h> +#include <wlr/types/wlr_cursor.h> +#include <wlr/types/wlr_data_device.h> +#include <wlr/types/wlr_input_device.h> +#include <wlr/types/wlr_keyboard.h> +#include <wlr/types/wlr_matrix.h> +#include <wlr/types/wlr_output.h> +#include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_pointer.h> +#include <wlr/types/wlr_seat.h> +#include <wlr/types/wlr_xcursor_manager.h> +#include <wlr/types/wlr_xdg_shell.h> +#include <wlr/util/log.h> +#include <wlr/xwayland.h> +#include <xkbcommon/xkbcommon.h> + +/* For brevity's sake, struct members are annotated where they are used. */ +enum tinywl_cursor_mode { + TINYWL_CURSOR_PASSTHROUGH, + TINYWL_CURSOR_MOVE, + TINYWL_CURSOR_RESIZE, +}; + +struct tinywl_server { + struct wl_display *wl_display; + struct wlr_backend *backend; + struct wlr_renderer *renderer; + + struct wlr_xdg_shell *xdg_shell; + struct wl_listener new_xdg_surface; + struct wl_list views; + + struct wlr_cursor *cursor; + struct wlr_xcursor_manager *cursor_mgr; + struct wl_listener cursor_motion; + struct wl_listener cursor_motion_absolute; + struct wl_listener cursor_button; + struct wl_listener cursor_axis; + struct wl_listener cursor_frame; + + struct wlr_seat *seat; + struct wl_listener new_input; + struct wl_listener request_cursor; + struct wl_listener request_set_selection; + struct wl_list keyboards; + enum tinywl_cursor_mode cursor_mode; + struct tinywl_view *grabbed_view; + double grab_x, grab_y; + struct wlr_box grab_geobox; + uint32_t resize_edges; + + struct wlr_output_layout *output_layout; + struct wl_list outputs; + struct wl_listener new_output; + + plugin_t plugin; +}; + +struct tinywl_output { + struct wl_list link; + struct tinywl_server *server; + struct wlr_output *wlr_output; + struct wl_listener frame; +}; + +struct tinywl_view { + struct wl_list link; + struct tinywl_server *server; + struct wlr_xdg_surface *xdg_surface; + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener request_move; + struct wl_listener request_resize; + bool mapped; + int x, y; +}; + +struct tinywl_keyboard { + struct wl_list link; + struct tinywl_server *server; + struct wlr_input_device *device; + + struct wl_listener modifiers; + struct wl_listener key; +}; diff --git a/harness/tools/genintf.pl b/harness/tools/genintf.pl index 12d525d..794f966 100644 --- a/harness/tools/genintf.pl +++ b/harness/tools/genintf.pl @@ -5,7 +5,7 @@ $comment=""; print "#ifndef _PLUG_INTF\n"; print "#define _PLUG_INTF\n"; print "\n#include <stdint.h>\n"; -print "\ntypedef void* opqst_t;\n"; +print "\n#include <plugin_types.h>\n"; while (<STDIN>) { if (/^\s*\/\*/) { diff --git a/src/Wetterhorn/Core.hs b/src/Wetterhorn/Core.hs index b5e4a6f..d3515fc 100644 --- a/src/Wetterhorn/Core.hs +++ b/src/Wetterhorn/Core.hs @@ -26,6 +26,7 @@ import Control.Exception import Control.Monad (when) import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as CH +import Data.Char (chr, ord) import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (fromMaybe) @@ -34,8 +35,7 @@ import Numeric (showHex) import Text.Printf import Wetterhorn.Core.ForeignInterface (ForeignInterface) import qualified Wetterhorn.Core.ForeignInterface as ForeignInterface -import Wetterhorn.WlRoots (WlrInputDevice, wlrSeatKeyboardNotifyKey, wlrSeatSetKeyboard) -import Data.Char (chr, ord) +import Wetterhorn.WlRoots data WContext = WContext { ctxForeignInterface :: ForeignInterface, @@ -88,7 +88,7 @@ data KeyEvent = KeyEvent data WConfig = WConfig { keybindingHandler :: KeyEvent -> W Bool, - surfaceHandler :: SurfaceState -> Ptr () -> W () + surfaceHandler :: SurfaceState -> Surface -> W () } defaultBindings :: Map (KeyState, Word32, Word32) (W ()) @@ -109,7 +109,6 @@ defaultConfig :: WConfig defaultConfig = WConfig { keybindingHandler = \keyEvent -> do - i <- incrementState seatPtr <- (wio . ForeignInterface.getSeat . ctxForeignInterface) =<< getWContext maybe @@ -130,7 +129,7 @@ defaultConfig = $ Map.lookup (state keyEvent, modifiers keyEvent, keysym keyEvent) defaultBindings, - surfaceHandler = \state ptr -> wio (printf "Surface %s is %s\n" (showHex (ptrToIntPtr ptr) "") (show state)) + surfaceHandler = \state surface -> wio (printf "Surface %s is %s\n" (show surface) (show state)) } readWState :: ByteString -> IO WState diff --git a/src/Wetterhorn/FFI.hs b/src/Wetterhorn/FFI.hs index 4be7189..6173291 100644 --- a/src/Wetterhorn/FFI.hs +++ b/src/Wetterhorn/FFI.hs @@ -17,10 +17,9 @@ import Foreign newStablePtr, ) import Foreign.C (CChar, CInt (..)) -import System.Posix.Types (CIno) import Wetterhorn.Core import Wetterhorn.Core.ForeignInterface -import Wetterhorn.WlRoots (WlrEventKeyboardKey, WlrInputDevice) +import Wetterhorn.WlRoots runForeign :: (WConfig -> W ()) -> Wetterhorn -> IO Wetterhorn runForeign fn stblptr = do @@ -123,23 +122,22 @@ pluginHandleKeybinding inputDevicePtr eventPtr mods sym cp = inputDevicePtr (\b -> if b then 1 else 0) <$> keybindingHandler config event -foreign export ccall "plugin_handle_surface_map" - pluginHandleSurfaceMap :: - Ptr () -> Wetterhorn -> IO Wetterhorn - -pluginHandleSurfaceMap :: Ptr () -> Wetterhorn -> IO Wetterhorn -pluginHandleSurfaceMap p = runForeign (\c -> surfaceHandler c Map p) - -foreign export ccall "plugin_handle_surface_unmap" - pluginHandleSurfaceUnmap :: - Ptr () -> Wetterhorn -> IO Wetterhorn - -pluginHandleSurfaceUnmap :: Ptr () -> Wetterhorn -> IO Wetterhorn -pluginHandleSurfaceUnmap p = runForeign (\c -> surfaceHandler c Unmap p) - -foreign export ccall "plugin_handle_surface_destroy" - pluginHandleSurfaceDestroy :: - Ptr () -> Wetterhorn -> IO Wetterhorn - -pluginHandleSurfaceDestroy :: Ptr () -> Wetterhorn -> IO Wetterhorn -pluginHandleSurfaceDestroy p = runForeign (\c -> surfaceHandler c Destroy p) +-- | Function exported to the harness to handle the mapping/unmapping/deletion +-- of an XDG surface. +foreign export ccall "plugin_handle_surface" + pluginHandleSurface :: + Ptr WlrXdgSurface -> CInt -> Wetterhorn -> IO Wetterhorn + +pluginHandleSurface :: Ptr WlrXdgSurface -> CInt -> Wetterhorn -> IO Wetterhorn +pluginHandleSurface p t = + runForeign (\c -> surfaceHandler c (toEnum $ fromIntegral t) (toSurface p)) + +-- | Function exported to the harness to handle the mapping/unmapping/deletion +-- of an XWayland surface. +foreign export ccall "plugin_handle_xwayland_surface" + pluginHandleXWaylandSurface :: + Ptr WlrXWaylandSurface -> CInt -> Wetterhorn -> IO Wetterhorn + +pluginHandleXWaylandSurface :: Ptr WlrXWaylandSurface -> CInt -> Wetterhorn -> IO Wetterhorn +pluginHandleXWaylandSurface p t = + runForeign (\c -> surfaceHandler c (toEnum $ fromIntegral t) (toSurface p)) diff --git a/src/Wetterhorn/WlRoots.hs b/src/Wetterhorn/WlRoots.hs new file mode 100644 index 0000000..7a2a237 --- /dev/null +++ b/src/Wetterhorn/WlRoots.hs @@ -0,0 +1,33 @@ +module Wetterhorn.WlRoots where + +import Foreign (Ptr, Word32) + +data WlrSeat + +data WlrInputDevice + +data WlrEventKeyboardKey + +data WlrXdgSurface + +data WlrXWaylandSurface + +data Surface + = XdgSurface (Ptr WlrXdgSurface) + | XWaylandSurface (Ptr WlrXWaylandSurface) + deriving (Show, Ord, Eq) + +class ForeignSurface a where + toSurface :: Ptr a -> Surface + +instance ForeignSurface WlrXdgSurface where + toSurface = XdgSurface + +instance ForeignSurface WlrXWaylandSurface where + toSurface = XWaylandSurface + +foreign import ccall "wlr_seat_set_keyboard" wlrSeatSetKeyboard :: Ptr WlrSeat -> Ptr WlrInputDevice -> IO () + +foreign import ccall "wlr_seat_keyboard_notify_key" + wlrSeatKeyboardNotifyKey :: + Ptr WlrSeat -> Word32 -> Word32 -> Word32 -> IO () |