diff --git a/12to11.c b/12to11.c index 88094d4..ed67ff6 100644 --- a/12to11.c +++ b/12to11.c @@ -225,6 +225,7 @@ XLMain (int argc, char **argv) XLInitTextInput (); XLInitSinglePixelBuffer (); XLInitDrmLease (); + XLInitPointerConstraints (); /* This has to come after the rest of the initialization. */ DetermineServerTime (); diff --git a/12to11.conf b/12to11.conf index 7ec91f4..f24aed1 100644 --- a/12to11.conf +++ b/12to11.conf @@ -18,6 +18,9 @@ WAYLAND_SCANNER = wayland-scanner /* Uncomment the following code if building with EGL support. */ XCOMM #define HaveEglSupport -XCOMM XCOMM EGL = -lEGL XCOMM GLES = -lGLESv2 + +XCOMM Local Variables: +XCOMM mode: makefile-imake +XCOMM End: diff --git a/12to11.man b/12to11.man index 73d6095..b3758f3 100644 --- a/12to11.man +++ b/12to11.man @@ -201,6 +201,7 @@ wp_viewporter 1 zxdg_decoration_manager_v1 1 zwp_text_input_manager_v3 1 wp_single_pixel_buffer_manager_v1 1 +zwp_pointer_constraints_v1 1 .TE .PP When the protocol translator is built with EGL support, the following diff --git a/Imakefile b/Imakefile index bfe3f07..8e2fd63 100644 --- a/Imakefile +++ b/Imakefile @@ -23,7 +23,7 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \ icon_surface.c primary_selection.c renderer.c \ picture_renderer.c explicit_synchronization.c transform.c \ wp_viewporter.c decoration.c text_input.c \ - single_pixel_buffer.c drm_lease.c + single_pixel_buffer.c drm_lease.c pointer_constraints.c OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \ surface.o region.o shm.o atoms.o subcompositor.o positioner.o \ @@ -33,7 +33,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \ icon_surface.o primary_selection.o renderer.o \ picture_renderer.o explicit_synchronization.o transform.o \ wp_viewporter.o decoration.o text_input.o \ - single_pixel_buffer.o drm_lease.o + single_pixel_buffer.o drm_lease.o pointer_constraints.o GENHEADERS = transfer_atoms.h @@ -117,6 +117,7 @@ ScannerTarget(xdg-decoration-unstable-v1) ScannerTarget(text-input-unstable-v3) ScannerTarget(single-pixel-buffer-v1) ScannerTarget(drm-lease-v1) +ScannerTarget(pointer-constraints-unstable-v1) /* Make OBJS depend on scanner headers, and depend on both them and SRCS. */ $(OBJS): $(GENHEADERS) diff --git a/README b/README index ba49a02..f6385d4 100644 --- a/README +++ b/README @@ -2,10 +2,7 @@ This is a tool for running Wayland applications on an X server, preferably with a compositing manager running. It is not yet complete. What is not yet implemented includes support -for touchscreens, input methods, device switching in dmabuf feedback, -and the single-pixel buffer protocol extension. - -There are also problems with output reporting in subsurfaces. +for touchscreens, and device switching in dmabuf feedback. It is not portable to systems other than recent versions of GNU/Linux running the X.Org server 1.20 or later, and has not been tested on @@ -20,20 +17,19 @@ extensions: Nonrectangular Window Shape Extension, version 1.1 or later MIT Shared Memory Extension, version 1.2 or later X Resize, Rotate and Reflect Extension, version 1.3 or later - (this will soon be 1.4, once support for multiple GPU - systems is fully implemented) X Synchronization Extension, version 1.0 or later X Rendering Extension, version 1.2 or later X Input Extension, version 2.3 or later Direct Rendering Interface 3, version 1.2 or later - X Fixes Extension, version 1 or later + X Fixes Extension, version 1.5 or later + X Presentation Extension, version 1.0 or later In addition, it requires Xlib to be built with the XCB transport, and the XCB bindings for MIT-SHM and DRI3 to be available. Sometimes, it might be desirable to build with EGL, and use OpenGL ES 2.0 for i.e. YUV video format support. To do so, uncomment the block -of code for EGL support in libraries.def before running `xmkmf'. This +of code for EGL support in 12to11.conf before running `xmkmf'. This will additionally require the EGL and GLESv2 development files, and for the following EGL and GLES extensions to be present at runtime: @@ -69,11 +65,18 @@ complete degree: 'zxdg_decoration_manager_v1', version: 1 'zwp_text_input_manager_v3', version: 1 'wp_single_pixel_buffer_manager_v1', version: 1 + 'zwp_pointer_constraints_v1', version: 1 When built with EGL, the following Wayland protocol is also supported: 'zwp_linux_explicit_synchronization_v1', version: 2 +When the X server supports version 1.6 or later of the X Resize, +Rotate and Reflect Extension, the following Wayland protocol is also +supported: + + 'wp_drm_lease_device_v1', version: 1 + With the main caveat being that zwp_linux_dmabuf_v1 has no real support for multiple-provider setups (help wanted). @@ -85,7 +88,7 @@ It would also be nice to have pinch gesture support. This directory is organized as follows: Imakefile - the top level Makefile template - libraries.def - files for libraries that don't provide Imakefiles + 12to11.conf - configuration *.xml - Wayland protocol definition source *.c, *.h - C source code *.awk - scripts used to generate headers @@ -93,7 +96,7 @@ This directory is organized as follows: those containing MIME types or shaders Building the source code is simple, provided that you have the -necessary libwayland-server library, pixman, XCB, and X extension +necessary libwayland-server library, pixman, XCB, DRM, and X extension libraries installed: xmkmf # to generate the Makefile diff --git a/compositor.h b/compositor.h index 4573c18..b4fb687 100644 --- a/compositor.h +++ b/compositor.h @@ -89,6 +89,7 @@ struct _Compositor /* Forward declarations from seat.c. */ typedef struct _Seat Seat; +typedef struct _Pointer Pointer; /* Forward declarations from primary_selection.c. */ @@ -749,6 +750,8 @@ extern void ViewClearViewport (View *); extern void ViewSetData (View *, void *); extern void *ViewGetData (View *); +extern void ViewSetMaybeResizedFunction (View *, void (*) (View *)); + extern void ViewTranslate (View *, int, int, int *, int *); extern void ViewFree (View *); @@ -860,6 +863,7 @@ typedef struct _DestroyCallback DestroyCallback; enum _ClientDataType { SubsurfaceData, + PointerConfinementData, MaxClientData, }; @@ -1398,9 +1402,15 @@ extern unsigned int XLSeatGetEffectiveModifiers (Seat *); extern Bool XLSeatResizeInProgress (Seat *); extern void XLSeatSetTextInputFuncs (TextInputFuncs *); extern int XLSeatGetKeyboardDevice (Seat *); +extern int XLSeatGetPointerDevice (Seat *); extern Seat *XLSeatGetInputMethodSeat (void); extern void XLSeatDispatchCoreKeyEvent (Seat *, Surface *, XEvent *, KeySym); +extern Seat *XLPointerGetSeat (Pointer *); +extern void XLSeatGetMouseData (Seat *, Surface **, double *, double *, + double *, double *); +extern void XLSeatLockPointer (Seat *); +extern void XLSeatUnlockPointer (Seat *); extern Cursor InitDefaultCursor (void); @@ -1554,10 +1564,20 @@ extern void XLInitDecoration (void); extern void XLInitSinglePixelBuffer (void); -/* Defined in drm_lease.h. */ +/* Defined in drm_lease.c. */ extern void XLInitDrmLease (void); +/* Defined in pointer_constraints.c. */ + +extern void XLInitPointerConstraints (void); +extern void XLPointerBarrierCheck (Seat *, Surface *, double, double, + double, double); +extern void XLPointerBarrierLeft (Seat *, Surface *); +extern void XLPointerConstraintsSurfaceMovedTo (Surface *, int, int); +extern void XLPointerConstraintsSubsurfaceMoved (Surface *); +extern void XLPointerConstraintsReconfineSurface (Surface *); + /* Utility functions that don't belong in a specific file. */ #define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0]) diff --git a/dmabuf.c b/dmabuf.c index db2ef56..c7c59f2 100644 --- a/dmabuf.c +++ b/dmabuf.c @@ -62,12 +62,12 @@ struct _BufferParams /* Entries for each plane. DRI3 only supports up to 4 planes. */ TemporarySetEntry entries[4]; - /* Some flags. */ - int flags; - /* The struct wl_resource associated with this object. */ struct wl_resource *resource; + /* Some flags. */ + int flags; + /* The width and height of the buffer that will be created. */ int width, height; }; @@ -80,15 +80,15 @@ struct _Buffer /* The RenderBuffer associated with this buffer. */ RenderBuffer render_buffer; - /* The width and height of this buffer. */ - unsigned int width, height; - /* The wl_resource corresponding to this buffer. */ struct wl_resource *resource; /* List of "destroy listeners" connected to this buffer. */ XLList *destroy_listeners; + /* The width and height of this buffer. */ + unsigned int width, height; + /* The number of references to this buffer. */ int refcount; }; diff --git a/dnd.c b/dnd.c index 14305d5..7b134b5 100644 --- a/dnd.c +++ b/dnd.c @@ -59,9 +59,6 @@ struct _DndState /* The target window. */ Window target_window; - /* The protocol version in use. */ - int proto; - /* The seat that is being used. */ Seat *seat; @@ -73,6 +70,19 @@ struct _DndState convenient. */ char **targets; + /* The timestamp to use for accessing selection data. */ + Time timestamp; + + /* The toplevel or child surface the pointer is currently + inside. */ + Surface *child; + + /* The unmap callback for that child. */ + UnmapCallback *unmap_callback; + + /* The protocol version in use. */ + int proto; + /* Number of targets in that array. */ int ntargets; @@ -111,16 +121,6 @@ struct _DndState /* Whether or not the drop has already happened. */ Bool dropped; - /* The timestamp to use for accessing selection data. */ - Time timestamp; - - /* The toplevel or child surface the pointer is currently - inside. */ - Surface *child; - - /* The unmap callback for that child. */ - UnmapCallback *unmap_callback; - /* The version of the XDND protocol being used. */ int version; }; @@ -153,6 +153,12 @@ struct _DragState /* The window cache. */ WindowCache *window_cache; + /* The time at which ownership of the selection was obtained. */ + Time timestamp; + + /* The selected action. */ + Atom action; + /* The last coordinates the pointer was seen at. */ int last_root_x, last_root_y; @@ -173,12 +179,6 @@ struct _DragState sent. */ XRectangle mouse_rect; - /* The time at which ownership of the selection was obtained. */ - Time timestamp; - - /* The selected action. */ - Atom action; - /* The modifiers currently held down. */ unsigned int modifiers; }; @@ -215,19 +215,9 @@ struct _WindowCacheEntry is really a WindowCacheEntryHeader. */ WindowCacheEntry *children; - /* The bounds of the window relative to its parents. */ - int x, y, width, height; - - /* Some flags. The protocol version is flags >> 16 & 0xff; 0 means - XDND is not supported. */ - int flags; - /* The XDND proxy window. Usually None. */ Window dnd_proxy; - /* The region describing its shape. */ - pixman_region32_t shape; - /* The window cache. */ WindowCache *cache; @@ -236,6 +226,16 @@ struct _WindowCacheEntry /* The key for input selection, if this is the root window. */ RootWindowSelection *input_key; + + /* The bounds of the window relative to its parents. */ + int x, y, width, height; + + /* Some flags. The protocol version is flags >> 16 & 0xff; 0 means + XDND is not supported. */ + int flags; + + /* The region describing its shape. */ + pixman_region32_t shape; }; /* The global drop state. */ diff --git a/seat.c b/seat.c index eb085a7..c477c4a 100644 --- a/seat.c +++ b/seat.c @@ -87,6 +87,7 @@ enum IsDragging = (1 << 3), IsDropped = (1 << 4), IsTextInputSeat = (1 << 5), + IsPointerLocked = (1 << 6), }; enum @@ -215,22 +216,22 @@ struct _SeatCursor /* The seat this cursor is for. */ Seat *seat; - /* The hotspot of the cursor. */ - int hotspot_x, hotspot_y; - /* The subcompositor for this cursor. */ Subcompositor *subcompositor; /* The frame callback for this cursor. */ void *cursor_frame_key; - /* Whether or not this cursor is currently keeping the cursor clock - active. */ - Bool holding_cursor_clock; - /* Ring of render targets for cursors. This allows updating the cursor while not creating a new render target each time. */ CursorRing *cursor_ring; + + /* The hotspot of the cursor. */ + int hotspot_x, hotspot_y; + + /* Whether or not this cursor is currently keeping the cursor clock + active. */ + Bool holding_cursor_clock; }; struct _ResizeDoneCallback @@ -250,8 +251,8 @@ struct _ScrollValuator /* The next scroll valuator in this list. */ ScrollValuator *next; - /* The direction of this valuator. */ - Direction direction; + /* The serial of the last event to have updated this valuator. */ + unsigned long enter_serial; /* The current value of this valuator. */ double value; @@ -262,8 +263,8 @@ struct _ScrollValuator /* The number of this valuator. */ int number; - /* The serial of the last event to have updated this valuator. */ - unsigned long enter_serial; + /* The direction of this valuator. */ + Direction direction; }; struct _Pointer @@ -309,17 +310,17 @@ struct _SeatClientInfo /* The next and last structures in the client info chain. */ SeatClientInfo *next, *last; - /* List of pointer objects on this seat for this client. */ - Pointer pointers; - - /* List of keyboard objects on this seat for this client. */ - Keyboard keyboards; - /* The client corresponding to this object. */ struct wl_client *client; + /* List of pointer objects on this seat for this client. */ + Pointer pointers; + /* The serial of the last enter event sent. */ uint32_t last_enter_serial; + + /* List of keyboard objects on this seat for this client. */ + Keyboard keyboards; }; struct _ModifierChangeCallback @@ -336,15 +337,15 @@ struct _ModifierChangeCallback struct _Seat { + /* wl_global associated with this seat. */ + struct wl_global *global; + /* XI device ID of the master keyboard device. */ int master_keyboard; /* XI device ID of the master pointer device. */ int master_pointer; - /* wl_global associated with this seat. */ - struct wl_global *global; - /* Number of references to this seat. */ int refcount; @@ -382,9 +383,6 @@ struct _Seat /* How many times the grab is held on this seat. */ int grab_held; - /* Array of keys currently held down. */ - struct wl_array keys; - /* Modifier masks. */ unsigned int base, locked, latched; @@ -402,42 +400,18 @@ struct _Seat /* The current cursor attached to this seat. */ SeatCursor *cursor; - /* The serial of the last button event sent. */ - uint32_t last_button_serial; - - /* The serial of the last button press event sent. GTK 4 sends this - even when grabbing a popup in response to a button release - event. */ - uint32_t last_button_press_serial; - - /* The last serial used to obtain a grab. */ - uint32_t last_grab_serial; - - /* The last edge used to obtain a grab. */ - WhatEdge last_grab_edge; - - /* The last timestamp used to obtain a grab. */ - Time last_grab_time; - - /* The button of the last button event sent, and the root_x and - root_y of the last button or motion event. */ - int last_button, its_root_x, its_root_y; - - /* When it was sent. */ - Time its_press_time; - - /* The serial of the last key event sent. */ - uint32_t last_keyboard_serial; - - /* The time of the last key event sent. */ - Time its_depress_time; - - /* Whether or not a resize is in progress. */ - Bool resize_in_progress; + /* The icon surface. */ + IconSurface *icon_surface; /* Callbacks run after a resize completes. */ ResizeDoneCallback resize_callbacks; + /* The drag-and-drop grab window. This is a 1x1 InputOnly window + with an empty input region at 0, 0, used to differentiate between + events delivered to a surface during drag and drop, and events + delivered due to the grab. */ + Window grab_window; + /* List of scroll valuators on this seat. */ ScrollValuator *valuators; @@ -453,6 +427,67 @@ struct _Seat /* Unmap callback for that surface. */ UnmapCallback *resize_surface_callback; + /* The last edge used to obtain a grab. */ + WhatEdge last_grab_edge; + + /* The last timestamp used to obtain a grab. */ + Time last_grab_time; + + /* When it was sent. */ + Time its_press_time; + + /* The time of the last key event sent. */ + Time its_depress_time; + + /* The grab surface. While it exists, events for different clients + will be reported relative to it. */ + Surface *grab_surface; + + /* The unmap callback. */ + UnmapCallback *grab_surface_callback; + + /* The data source for drag-and-drop. */ + DataSource *data_source; + + /* The destroy callback for the data source. */ + void *data_source_destroy_callback; + + /* The surface on which this drag operation started. */ + Surface *drag_start_surface; + + /* The UnmapCallback for that surface. */ + UnmapCallback *drag_start_unmap_callback; + + /* The last surface to be entered during drag-and-drop. */ + Surface *drag_last_surface; + + /* The destroy callback for that surface. */ + DestroyCallback *drag_last_surface_destroy_callback; + + /* The time the active grab was acquired. */ + Time drag_grab_time; + + /* The button of the last button event sent, and the root_x and + root_y of the last button or motion event. */ + int last_button, its_root_x, its_root_y; + + /* The serial of the last button event sent. */ + uint32_t last_button_serial; + + /* The serial of the last button press event sent. GTK 4 sends this + even when grabbing a popup in response to a button release + event. */ + uint32_t last_button_press_serial; + + /* The last serial used to obtain a grab. */ + uint32_t last_grab_serial; + + /* The serial of the last key event sent. */ + uint32_t last_keyboard_serial; + + /* Whether or not a resize is in progress. */ + Bool resize_in_progress; + /* Where that resize started. */ int resize_start_root_x, resize_start_root_y; @@ -483,45 +518,14 @@ struct _Seat /* The root_x and root_y of the last motion or crossing event. */ double last_motion_x, last_motion_y; - /* The grab surface. While it exists, events for different clients - will be reported relative to it. */ - Surface *grab_surface; - - /* The unmap callback. */ - UnmapCallback *grab_surface_callback; - - /* The data source for drag-and-drop. */ - DataSource *data_source; - - /* The destroy callback for the data source. */ - void *data_source_destroy_callback; - - /* The surface on which this drag operation started. */ - Surface *drag_start_surface; - - /* The UnmapCallback for that surface. */ - UnmapCallback *drag_start_unmap_callback; - - /* The last surface to be entered during drag-and-drop. */ - Surface *drag_last_surface; - - /* The destroy callback for that surface. */ - DestroyCallback *drag_last_surface_destroy_callback; - - /* The time the active grab was acquired. */ - Time drag_grab_time; - - /* The icon surface. */ - IconSurface *icon_surface; - - /* The drag-and-drop grab window. This is a 1x1 InputOnly window - with an empty input region at 0, 0, used to differentiate between - events delivered to a surface during drag and drop, and events - delivered due to the grab. */ - Window grab_window; + /* The x and y of the last surface movement. */ + double last_surface_x, last_surface_y; /* List of all modifier change callbacks attached to this seat. */ ModifierChangeCallback modifier_callbacks; + + /* Array of keys currently held down. */ + struct wl_array keys; }; struct _DeviceInfo @@ -3056,9 +3060,13 @@ SendMotion (Seat *seat, Surface *surface, double x, double y, pointer->info->last_enter_serial = serial; } - wl_pointer_send_motion (pointer->resource, time, - wl_fixed_from_double (x), - wl_fixed_from_double (y)); + /* If the seat is locked, don't send any motion events at + all. */ + + if (!(seat->flags & IsPointerLocked)) + wl_pointer_send_motion (pointer->resource, time, + wl_fixed_from_double (x), + wl_fixed_from_double (y)); if (wl_resource_get_version (pointer->resource) >= 5) wl_pointer_send_frame (pointer->resource); @@ -3312,6 +3320,10 @@ EnteredSurface (Seat *seat, Surface *surface, Time time, FreeCursor (seat->cursor); } + /* Cancel any pointer confinement. */ + XLPointerBarrierLeft (seat, seat->last_seen_surface); + + /* Clear the surface. */ XLSurfaceCancelRunOnFree (seat->last_seen_surface_callback); seat->last_seen_surface = NULL; seat->last_seen_surface_callback = NULL; @@ -3322,6 +3334,8 @@ EnteredSurface (Seat *seat, Surface *surface, Time time, seat->last_seen_surface = surface; seat->last_seen_surface_callback = XLSurfaceRunOnFree (surface, ClearLastSeenSurface, seat); + seat->last_surface_x = x; + seat->last_surface_y = y; if (seat->flags & IsDragging) DragEnter (seat, surface, x, y); @@ -3681,6 +3695,16 @@ HandleValuatorMotion (Seat *seat, Surface *dispatch, double x, double y, return value; } +static void +CheckPointerBarrier (Seat *seat, Surface *dispatch, double x, double y, + double root_x, double root_y) +{ + /* Check if DISPATCH has a pointer confinement that would be + activated by this motion. */ + + XLPointerBarrierCheck (seat, dispatch, x, y, root_x, root_y); +} + static void DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev) { @@ -3774,7 +3798,19 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev) if (seat->flags & IsDragging) DragMotion (seat, dispatch, x, y, xev->time); else - SendMotion (seat, dispatch, x, y, xev->time); + { + /* Send the motion event. */ + SendMotion (seat, dispatch, x, y, xev->time); + + /* Check if this motion would cause a pointer constraint to + activate. */ + CheckPointerBarrier (seat, dispatch, x, y, xev->root_x, + xev->root_y); + } + + /* Set the last movement location. */ + seat->last_surface_x = x; + seat->last_surface_y = y; } /* These values are for tracking the output that a cursor is in. */ @@ -5422,6 +5458,12 @@ XLSeatGetKeyboardDevice (Seat *seat) return seat->master_keyboard; } +int +XLSeatGetPointerDevice (Seat *seat) +{ + return seat->master_pointer; +} + Seat * XLSeatGetInputMethodSeat (void) { @@ -5509,3 +5551,33 @@ XLSeatDispatchCoreKeyEvent (Seat *seat, Surface *surface, XEvent *event, if (group != seat->effective_group || state != effective) SendKeyboardModifiers (seat, surface); } + +Seat * +XLPointerGetSeat (Pointer *pointer) +{ + return pointer->seat; +} + +void +XLSeatGetMouseData (Seat *seat, Surface **last_seen_surface, + double *last_surface_x, double *last_surface_y, + double *its_root_x, double *its_root_y) +{ + *last_seen_surface = seat->last_seen_surface; + *last_surface_x = seat->last_surface_x; + *last_surface_y = seat->last_surface_y; + *its_root_x = seat->its_root_x; + *its_root_y = seat->its_root_y; +} + +void +XLSeatLockPointer (Seat *seat) +{ + seat->flags |= IsPointerLocked; +} + +void +XLSeatUnlockPointer (Seat *seat) +{ + seat->flags &= ~IsPointerLocked; +} diff --git a/shm.c b/shm.c index e2f6406..239e531 100644 --- a/shm.c +++ b/shm.c @@ -74,9 +74,6 @@ typedef struct _Buffer int refcount; } Buffer; -/* List of all resources for our shared memory global. */ -static XLList *all_shms; - /* The shared memory global. */ static struct wl_global *global_shm; @@ -412,12 +409,6 @@ static const struct wl_shm_pool_interface wl_shm_pool_impl = .create_buffer = CreateBuffer, }; -static void -HandleResourceDestroy (struct wl_resource *resource) -{ - all_shms = XLListRemove (all_shms, resource); -} - static void CreatePool (struct wl_client *client, struct wl_resource *resource, uint32_t id, int32_t fd, int32_t size) @@ -533,8 +524,7 @@ HandleBind (struct wl_client *client, void *data, } wl_resource_set_implementation (resource, &wl_shm_impl, - NULL, HandleResourceDestroy); - all_shms = XLListPrepend (all_shms, resource); + NULL, NULL); PostFormats (resource); } diff --git a/subcompositor.c b/subcompositor.c index 179fa14..b2771e9 100644 --- a/subcompositor.c +++ b/subcompositor.c @@ -273,6 +273,9 @@ struct _View attached. */ ExtBuffer *buffer; + /* Function called upon the view potentially being resized. */ + void (*maybe_resized) (View *); + /* The damaged and opaque regions. */ pixman_region32_t damage, opaque; @@ -1262,7 +1265,8 @@ main (int argc, char **argv) /* Notice that VIEW's size has changed, while VIEW itself has not moved. Recompute the max_x, min_x, min_y, and max_y of its - subcompositor. */ + subcompositor. In addition, run the view's resize function, if + any. */ static void ViewAfterSizeUpdate (View *view) @@ -1270,6 +1274,9 @@ ViewAfterSizeUpdate (View *view) int doflags; Bool mapped; + if (view->maybe_resized) + view->maybe_resized (view); + if (!view->subcompositor || !ViewVisibilityState (view, &mapped) || !mapped || IsSkipped (view)) return; @@ -1332,7 +1339,7 @@ ViewAttachBuffer (View *view, ExtBuffer *buffer) as well. */ SetGarbaged (view->subcompositor); - /* Recompute view bounds. */ + /* Recompute view and subcompositor bounds. */ ViewAfterSizeUpdate (view); } } @@ -2991,6 +2998,12 @@ ViewSetData (View *view, void *data) view->data = data; } +void +ViewSetMaybeResizedFunction (View *view, void (*func) (View *)) +{ + view->maybe_resized = func; +} + void ViewTranslate (View *view, int x, int y, int *x_out, int *y_out) { diff --git a/subsurface.c b/subsurface.c index d5b3323..92ce10a 100644 --- a/subsurface.c +++ b/subsurface.c @@ -557,6 +557,9 @@ MoveFractional (Subsurface *subsurface) purposes. */ subsurface->role.surface->input_delta_x = x - x_int; subsurface->role.surface->input_delta_y = y - y_int; + + /* Apply pointer constraints. */ + XLPointerConstraintsSubsurfaceMoved (subsurface->role.surface); } static void diff --git a/surface.c b/surface.c index 5b9a4b0..aab4da1 100644 --- a/surface.c +++ b/surface.c @@ -634,6 +634,10 @@ ApplyInputRegion (Surface *surface) ViewSetInput (surface->view, &temp); pixman_region32_fini (&temp); } + + /* The input region has changed, so pointer confinement must be + redone. */ + XLPointerConstraintsReconfineSurface (surface); } static void @@ -828,6 +832,9 @@ HandleScaleChanged (void *data, int new_scale) surface->role->funcs.end_subframe (surface, surface->role); } } + + /* The scale has changed, so pointer confinement must be redone. */ + XLPointerConstraintsReconfineSurface (surface); } static void @@ -1428,6 +1435,18 @@ HandleSurfaceDestroy (struct wl_resource *resource) XLFree (surface); } +static void +MaybeResized (View *view) +{ + Surface *surface; + + surface = ViewGetData (view); + + /* The view may have been resized; recompute pointer confinement + area if necessary. */ + XLPointerConstraintsReconfineSurface (surface); +} + void XLCreateSurface (struct wl_client *client, struct wl_resource *resource, @@ -1468,6 +1487,9 @@ XLCreateSurface (struct wl_client *client, view. */ ViewSetData (surface->view, surface); + /* Make it so pointer confinement stuff can run after resize. */ + ViewSetMaybeResizedFunction (surface->view, MaybeResized); + /* Initialize the sentinel node for the commit callback list. */ surface->commit_callbacks.last = &surface->commit_callbacks; surface->commit_callbacks.next = &surface->commit_callbacks; @@ -1702,8 +1724,7 @@ Window XLWindowFromSurface (Surface *surface) { if (!surface->role - || !surface->role->funcs.get_window (surface, - surface->role)) + || !surface->role->funcs.get_window) return None; return surface->role->funcs.get_window (surface, diff --git a/xdata.c b/xdata.c index 46491b8..8040a4c 100644 --- a/xdata.c +++ b/xdata.c @@ -50,11 +50,11 @@ struct _ReadTargetsData /* Array of atoms read from the selection. */ Atom *atoms; - /* Number of atoms read. */ - int n_atoms; - /* What selection is being read from. */ Atom selection; + + /* Number of atoms read. */ + int n_atoms; }; struct _TargetMapping @@ -145,11 +145,11 @@ struct _ConversionTransferInfo /* And the amount of data used in the output buffer. */ size_t outsize; - /* The data format conversion context. */ - iconv_t cd; - /* Any active file descriptor write callback. */ WriteFd *write_callback; + + /* The data format conversion context. */ + iconv_t cd; }; enum @@ -201,17 +201,17 @@ struct _ConversionWriteInfo struct _TargetMappingTable { - /* Array of indices into direct_transfer. */ - unsigned short *buckets[32]; - - /* Number of elements in each array. */ - unsigned short n_elements[32]; - /* Array of indices into direct_transfer. */ unsigned short *atom_buckets[16]; - /* Number of elements in each array. */ + /* Array of indices into direct_transfer. */ + unsigned short *buckets[32]; + + /* Number of elements in each atom bucket. */ unsigned short n_atom_elements[16]; + + /* Number of elements in each bucket. */ + unsigned short n_elements[32]; }; /* Base event code of the Xfixes extension. */ @@ -2228,7 +2228,7 @@ XLInitXData (void) rc = XFixesQueryVersion (compositor.display, &major, &minor); - if (!rc || major < 1) + if (!rc || major < 5) { fprintf (stderr, "The X server does not support the " "right version of the XFixes protocol extension\n"); diff --git a/xdg_surface.c b/xdg_surface.c index aac7a47..2fab550 100644 --- a/xdg_surface.c +++ b/xdg_surface.c @@ -90,11 +90,6 @@ struct _XdgRole /* The role object. */ Role role; - /* Number of references to this role. Used when the client - terminates and the Wayland library destroys objects out of - order. */ - int refcount; - /* The window backing this role. */ Window window; @@ -110,6 +105,11 @@ struct _XdgRole /* The pending frame ID. */ uint64_t pending_frame; + /* Number of references to this role. Used when the client + terminates and the Wayland library destroys objects out of + order. */ + int refcount; + /* Various role state. */ int state; @@ -126,6 +126,9 @@ struct _XdgRole /* The current xdg_surface state. */ XdgState current_state; + /* List of callbacks run upon a ConfigureNotify event. */ + ReconstrainCallback reconstrain_callbacks; + /* Configure event serial. */ uint32_t conf_serial, last_specified_serial; @@ -142,17 +145,14 @@ struct _XdgRole events to wait for before ignoring those coordinates. */ int pending_synth_configure; - /* The type of the attached role. */ - XdgRoleImplementationType type; - /* The input region of the attached subsurface. */ pixman_region32_t input_region; - /* List of callbacks run upon a ConfigureNotify event. */ - ReconstrainCallback reconstrain_callbacks; - /* The number of desynchronous children of this toplevel. */ int n_desync_children; + + /* The type of the attached role. */ + XdgRoleImplementationType type; }; struct _ReleaseLaterRecord @@ -537,15 +537,7 @@ AckConfigure (struct wl_client *client, struct wl_resource *resource, fprintf (stderr, "ack_configure: %"PRIu32"\n", serial); #endif - if (serial < xdg_role->conf_serial) - { - /* The client specified an outdated serial. */ - wl_resource_post_error (resource, XDG_SURFACE_ERROR_INVALID_SERIAL, - "serial specified not monotonic"); - return; - } - - if (serial && serial == xdg_role->last_specified_serial) + if (serial && serial <= xdg_role->last_specified_serial) { /* The client specified the same serial twice. */ wl_resource_post_error (resource, XDG_SURFACE_ERROR_INVALID_SERIAL, @@ -1005,12 +997,19 @@ NoteConfigure (XdgRole *role, XEvent *event) if (role->pending_synth_configure) role->pending_synth_configure--; - /* Update the surface that the surface is inside. */ if (role->role.surface) - XLUpdateSurfaceOutputs (role->role.surface, - event->xconfigure.x + role->min_x, - event->xconfigure.y + role->min_y, - -1, -1); + { + /* Update the list of outputs that the surface is inside. */ + XLUpdateSurfaceOutputs (role->role.surface, + event->xconfigure.x + role->min_x, + event->xconfigure.y + role->min_y, + -1, -1); + + /* Update pointer constraints. */ + XLPointerConstraintsSurfaceMovedTo (role->role.surface, + event->xconfigure.x, + event->xconfigure.y); + } RunReconstrainCallbacksForXEvent (role, event); } diff --git a/xdg_toplevel.c b/xdg_toplevel.c index d73490c..bd8e3df 100644 --- a/xdg_toplevel.c +++ b/xdg_toplevel.c @@ -134,26 +134,6 @@ struct _XdgToplevel /* The wl_resource associated with this toplevel. */ struct wl_resource *resource; - /* The number of references to this toplevel. */ - int refcount; - - /* Some state associated with this toplevel. */ - int state; - - /* The serial of the last configure sent. */ - uint32_t conf_serial; - - /* Whether or not we are waiting for a reply to a configure - event. */ - Bool conf_reply; - - /* Array of states. */ - struct wl_array states; - - /* The current width and height of this toplevel as received in the - last ConfigureNotify event. */ - int width, height; - /* The Motif window manager hints associated with this toplevel. */ PropMotifWmHints motif; @@ -163,22 +143,14 @@ struct _XdgToplevel /* All resize callbacks currently posted. */ XLList *resize_callbacks; - /* Minimum size of this toplevel. */ - int min_width, min_height; - - /* Maximim size of this toplevel. */ - int max_width, max_height; - - /* Pending values. */ - int pending_max_width, pending_max_height; - int pending_min_height, pending_min_width; - - /* How much to move upon the next ack_configure. Used to resize a - window westwards or northwards. */ - int ack_west, ack_north; - - /* X Windows size hints. */ - XSizeHints size_hints; + /* Timer for completing window state changes. The order of + _NET_WM_STATE changes and ConfigureNotify events is not + predictable, so we batch up both kinds of events with a 0.01 + second delay by default, before sending the resulting + ConfigureNotify event. However, if drag-to-resize is in + progress, no such delay is effected. */ +#define DefaultStateDelayNanoseconds 10000000 + Timer *configuration_timer; /* List of callbacks run upon unmapping. The callbacks are then deleted. */ @@ -190,6 +162,9 @@ struct _XdgToplevel /* The unmap callback for the parent toplevel. */ XdgUnmapCallback *parent_callback; + /* Any decoration resource associated with this toplevel. */ + XdgDecoration *decoration; + /* Various geometries before a given state change. width00/height00 mean the size when the toplevel was neither @@ -210,6 +185,20 @@ struct _XdgToplevel int width01, height01, width10, height10; int width00, height00, width11, height11; + /* Minimum size of this toplevel. */ + int min_width, min_height; + + /* Maximim size of this toplevel. */ + int max_width, max_height; + + /* Pending values. */ + int pending_max_width, pending_max_height; + int pending_min_height, pending_min_width; + + /* How much to move upon the next ack_configure. Used to resize a + window westwards or northwards. */ + int ack_west, ack_north; + /* The width, height, west and north motion of the next resize. */ int resize_width, resize_height, resize_west, resize_north; @@ -218,24 +207,35 @@ struct _XdgToplevel _NET_WM_ALLOWED_ACTIONS. */ int supported; - /* Timer for completing window state changes. The order of - _NET_WM_STATE changes and ConfigureNotify events is not - predictable, so we batch up both kinds of events with a 0.01 - second delay by default, before sending the resulting - ConfigureNotify event. However, if drag-to-resize is in - progress, no such delay is effected. */ -#define DefaultStateDelayNanoseconds 10000000 - Timer *configuration_timer; + /* The number of references to this toplevel. */ + int refcount; + + /* Some state associated with this toplevel. */ + int state; + + /* The serial of the last configure sent. */ + uint32_t conf_serial; + + /* Whether or not we are waiting for a reply to a configure + event. */ + Bool conf_reply; + + /* The current width and height of this toplevel as received in the + last ConfigureNotify event. */ + int width, height; /* The width and height used by that timer if StatePendingConfigureSize is set. */ int configure_width, configure_height; - /* Any decoration resource associated with this toplevel. */ - XdgDecoration *decoration; + /* Array of states. */ + struct wl_array states; /* The decoration mode. */ DecorationMode decor; + + /* X Windows size hints. */ + XSizeHints size_hints; }; struct _XdgDecoration