aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2024-02-22 16:07:54 -0700
committerJosh Rahm <rahm@google.com>2024-02-22 16:08:38 -0700
commit320d4a87447491abd1fa0cfa898bd6b5ae73dee9 (patch)
tree923347ae3fbcef1b3fe20ca4f6fca69fda3ff05b
parent0724c6d9cd77d83bd113204bdec5ac23491c35d7 (diff)
downloadwetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.tar.gz
wetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.tar.bz2
wetterhorn-320d4a87447491abd1fa0cfa898bd6b5ae73dee9.zip
better surface handling
-rw-r--r--harness/include/plugin.h7
-rw-r--r--harness/include/plugin_types.h9
-rw-r--r--harness/src/wl.c12
-rw-r--r--harness/src/wl.h95
-rw-r--r--harness/tools/genintf.pl2
-rw-r--r--src/Wetterhorn/Core.hs9
-rw-r--r--src/Wetterhorn/FFI.hs42
-rw-r--r--src/Wetterhorn/WlRoots.hs33
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 ()