mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	cursor: Store view + resize edges for move/resize in press event
v2: Restore previous behavior for keybinds
This commit is contained in:
		
							parent
							
								
									429c388333
								
							
						
					
					
						commit
						1fafb89cba
					
				
					 5 changed files with 60 additions and 29 deletions
				
			
		| 
						 | 
					@ -103,19 +103,22 @@ struct seat {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * pressed view/surface/node will usually be NULL and is only set on
 | 
						 * pressed view/surface/node will usually be NULL and is only set on
 | 
				
			||||||
	 * button press while the mouse is over a surface and reset to NULL on
 | 
						 * button press while the mouse is over a view or surface, and reset
 | 
				
			||||||
	 * button release.
 | 
						 * to NULL on button release.
 | 
				
			||||||
	 * It is used to send cursor motion events to a surface even though
 | 
						 * It is used to send cursor motion events to a surface even though
 | 
				
			||||||
	 * the cursor has left the surface in the meantime.
 | 
						 * the cursor has left the surface in the meantime.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * This allows to keep dragging a scrollbar or selecting text even
 | 
						 * This allows to keep dragging a scrollbar or selecting text even
 | 
				
			||||||
	 * when moving outside of the window.
 | 
						 * when moving outside of the window.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Both (view && !surface) and (surface && !view) are possible.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct view *view;
 | 
							struct view *view;
 | 
				
			||||||
		struct wlr_scene_node *node;
 | 
							struct wlr_scene_node *node;
 | 
				
			||||||
		struct wlr_surface *surface;
 | 
							struct wlr_surface *surface;
 | 
				
			||||||
		struct wlr_surface *toplevel;
 | 
							struct wlr_surface *toplevel;
 | 
				
			||||||
 | 
							uint32_t resize_edges;
 | 
				
			||||||
	} pressed;
 | 
						} pressed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_client *active_client_while_inhibited;
 | 
						struct wl_client *active_client_while_inhibited;
 | 
				
			||||||
| 
						 | 
					@ -569,7 +572,7 @@ void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
 | 
				
			||||||
void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
 | 
					void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
 | 
				
			||||||
void seat_set_pressed(struct seat *seat, struct view *view,
 | 
					void seat_set_pressed(struct seat *seat, struct view *view,
 | 
				
			||||||
	struct wlr_scene_node *node, struct wlr_surface *surface,
 | 
						struct wlr_scene_node *node, struct wlr_surface *surface,
 | 
				
			||||||
	struct wlr_surface *toplevel);
 | 
						struct wlr_surface *toplevel, uint32_t resize_edges);
 | 
				
			||||||
void seat_reset_pressed(struct seat *seat);
 | 
					void seat_reset_pressed(struct seat *seat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void interactive_begin(struct view *view, enum input_mode mode,
 | 
					void interactive_begin(struct view *view, enum input_mode mode,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/action.c
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								src/action.c
									
										
									
									
									
								
							| 
						 | 
					@ -166,9 +166,23 @@ show_menu(struct server *server, struct view *view, const char *menu_name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct view *
 | 
					static struct view *
 | 
				
			||||||
activator_or_focused_view(struct view *activator, struct server *server)
 | 
					view_for_action(struct view *activator, struct server *server,
 | 
				
			||||||
 | 
						struct action *action)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return activator ? activator : desktop_focused_view(server);
 | 
						/* View is explicitly specified for mousebinds */
 | 
				
			||||||
 | 
						if (activator) {
 | 
				
			||||||
 | 
							return activator;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Select view based on action type for keybinds */
 | 
				
			||||||
 | 
						switch (action->type) {
 | 
				
			||||||
 | 
						case ACTION_TYPE_FOCUS:
 | 
				
			||||||
 | 
						case ACTION_TYPE_MOVE:
 | 
				
			||||||
 | 
						case ACTION_TYPE_RESIZE:
 | 
				
			||||||
 | 
							return get_cursor_context(server).view;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return desktop_focused_view(server);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -194,7 +208,7 @@ actions_run(struct view *activator, struct server *server,
 | 
				
			||||||
		 * Refetch view because it may have been changed due to the
 | 
							 * Refetch view because it may have been changed due to the
 | 
				
			||||||
		 * previous action
 | 
							 * previous action
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		view = activator_or_focused_view(activator, server);
 | 
							view = view_for_action(activator, server, action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (action->type) {
 | 
							switch (action->type) {
 | 
				
			||||||
		case ACTION_TYPE_CLOSE:
 | 
							case ACTION_TYPE_CLOSE:
 | 
				
			||||||
| 
						 | 
					@ -275,7 +289,6 @@ actions_run(struct view *activator, struct server *server,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case ACTION_TYPE_FOCUS:
 | 
							case ACTION_TYPE_FOCUS:
 | 
				
			||||||
			view = get_cursor_context(server).view;
 | 
					 | 
				
			||||||
			if (view) {
 | 
								if (view) {
 | 
				
			||||||
				desktop_focus_and_activate_view(&server->seat, view);
 | 
									desktop_focus_and_activate_view(&server->seat, view);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -286,7 +299,6 @@ actions_run(struct view *activator, struct server *server,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case ACTION_TYPE_MOVE:
 | 
							case ACTION_TYPE_MOVE:
 | 
				
			||||||
			view = get_cursor_context(server).view;
 | 
					 | 
				
			||||||
			if (view) {
 | 
								if (view) {
 | 
				
			||||||
				interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
 | 
									interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -297,7 +309,6 @@ actions_run(struct view *activator, struct server *server,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case ACTION_TYPE_RESIZE:
 | 
							case ACTION_TYPE_RESIZE:
 | 
				
			||||||
			view = get_cursor_context(server).view;
 | 
					 | 
				
			||||||
			if (view) {
 | 
								if (view) {
 | 
				
			||||||
				interactive_begin(view, LAB_INPUT_STATE_RESIZE,
 | 
									interactive_begin(view, LAB_INPUT_STATE_RESIZE,
 | 
				
			||||||
					resize_edges);
 | 
										resize_edges);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/cursor.c
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								src/cursor.c
									
										
									
									
									
								
							| 
						 | 
					@ -255,8 +255,10 @@ update_pressed_surface(struct seat *seat, struct cursor_context *ctx)
 | 
				
			||||||
	if (seat->pressed.surface && ctx->surface != seat->pressed.surface) {
 | 
						if (seat->pressed.surface && ctx->surface != seat->pressed.surface) {
 | 
				
			||||||
		struct wlr_surface *toplevel = get_toplevel(ctx->surface);
 | 
							struct wlr_surface *toplevel = get_toplevel(ctx->surface);
 | 
				
			||||||
		if (toplevel && toplevel == seat->pressed.toplevel) {
 | 
							if (toplevel && toplevel == seat->pressed.toplevel) {
 | 
				
			||||||
			seat_set_pressed(seat, ctx->view, ctx->node,
 | 
								/* No need to recompute resize edges here */
 | 
				
			||||||
				ctx->surface, toplevel);
 | 
								seat_set_pressed(seat, ctx->view,
 | 
				
			||||||
 | 
									ctx->node, ctx->surface, toplevel,
 | 
				
			||||||
 | 
									seat->pressed.resize_edges);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -424,12 +426,15 @@ process_cursor_motion(struct server *server, uint32_t time)
 | 
				
			||||||
	wl_list_for_each(mousebind, &rc.mousebinds, link) {
 | 
						wl_list_for_each(mousebind, &rc.mousebinds, link) {
 | 
				
			||||||
		if (mousebind->mouse_event == MOUSE_ACTION_DRAG
 | 
							if (mousebind->mouse_event == MOUSE_ACTION_DRAG
 | 
				
			||||||
				&& mousebind->pressed_in_context) {
 | 
									&& mousebind->pressed_in_context) {
 | 
				
			||||||
			/* Find closest resize edges in case action is Resize */
 | 
								/*
 | 
				
			||||||
			uint32_t resize_edges =
 | 
								 * Use view and resize edges from the press
 | 
				
			||||||
				determine_resize_edges(seat->cursor, &ctx);
 | 
								 * event (not the motion event) to prevent
 | 
				
			||||||
 | 
								 * moving/resizing the wrong view
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
			mousebind->pressed_in_context = false;
 | 
								mousebind->pressed_in_context = false;
 | 
				
			||||||
			actions_run(NULL, server, &mousebind->actions, resize_edges);
 | 
								actions_run(seat->pressed.view,
 | 
				
			||||||
 | 
									server, &mousebind->actions,
 | 
				
			||||||
 | 
									seat->pressed.resize_edges);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -825,9 +830,13 @@ cursor_button(struct wl_listener *listener, void *data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Handle _press */
 | 
						/* Handle _press */
 | 
				
			||||||
	if (ctx.surface) {
 | 
						/* Determine closest resize edges in case action is Resize */
 | 
				
			||||||
 | 
						resize_edges = determine_resize_edges(seat->cursor, &ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ctx.view || ctx.surface) {
 | 
				
			||||||
 | 
							/* Store resize edges for later action processing */
 | 
				
			||||||
		seat_set_pressed(seat, ctx.view, ctx.node, ctx.surface,
 | 
							seat_set_pressed(seat, ctx.view, ctx.node, ctx.surface,
 | 
				
			||||||
			get_toplevel(ctx.surface));
 | 
								get_toplevel(ctx.surface), resize_edges);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (server->input_mode == LAB_INPUT_STATE_MENU) {
 | 
						if (server->input_mode == LAB_INPUT_STATE_MENU) {
 | 
				
			||||||
| 
						 | 
					@ -850,9 +859,6 @@ cursor_button(struct wl_listener *listener, void *data)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Determine closest resize edges in case action is Resize */
 | 
					 | 
				
			||||||
	resize_edges = determine_resize_edges(seat->cursor, &ctx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mousebindings:
 | 
					mousebindings:
 | 
				
			||||||
	if (event->state == WLR_BUTTON_RELEASED) {
 | 
						if (event->state == WLR_BUTTON_RELEASED) {
 | 
				
			||||||
		triggered_frame_binding |= handle_release_mousebinding(ctx.view,
 | 
							triggered_frame_binding |= handle_release_mousebinding(ctx.view,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/seat.c
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								src/seat.c
									
										
									
									
									
								
							| 
						 | 
					@ -384,27 +384,34 @@ pressed_surface_destroy(struct wl_listener *listener, void *data)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
seat_set_pressed(struct seat *seat, struct view *view,
 | 
					seat_set_pressed(struct seat *seat, struct view *view,
 | 
				
			||||||
	struct wlr_scene_node *node, struct wlr_surface *surface,
 | 
						struct wlr_scene_node *node, struct wlr_surface *surface,
 | 
				
			||||||
	struct wlr_surface *toplevel)
 | 
						struct wlr_surface *toplevel, uint32_t resize_edges)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	assert(surface);
 | 
						assert(view || surface);
 | 
				
			||||||
	seat_reset_pressed(seat);
 | 
						seat_reset_pressed(seat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seat->pressed.view = view;
 | 
						seat->pressed.view = view;
 | 
				
			||||||
	seat->pressed.node = node;
 | 
						seat->pressed.node = node;
 | 
				
			||||||
	seat->pressed.surface = surface;
 | 
						seat->pressed.surface = surface;
 | 
				
			||||||
	seat->pressed.toplevel = toplevel;
 | 
						seat->pressed.toplevel = toplevel;
 | 
				
			||||||
 | 
						seat->pressed.resize_edges = resize_edges;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (surface) {
 | 
				
			||||||
		seat->pressed_surface_destroy.notify = pressed_surface_destroy;
 | 
							seat->pressed_surface_destroy.notify = pressed_surface_destroy;
 | 
				
			||||||
	wl_signal_add(&surface->events.destroy, &seat->pressed_surface_destroy);
 | 
							wl_signal_add(&surface->events.destroy,
 | 
				
			||||||
 | 
								&seat->pressed_surface_destroy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
seat_reset_pressed(struct seat *seat)
 | 
					seat_reset_pressed(struct seat *seat)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (seat->pressed.surface) {
 | 
						if (seat->pressed.surface) {
 | 
				
			||||||
 | 
							wl_list_remove(&seat->pressed_surface_destroy.link);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seat->pressed.view = NULL;
 | 
						seat->pressed.view = NULL;
 | 
				
			||||||
	seat->pressed.node = NULL;
 | 
						seat->pressed.node = NULL;
 | 
				
			||||||
	seat->pressed.surface = NULL;
 | 
						seat->pressed.surface = NULL;
 | 
				
			||||||
	seat->pressed.toplevel = NULL;
 | 
						seat->pressed.toplevel = NULL;
 | 
				
			||||||
		wl_list_remove(&seat->pressed_surface_destroy.link);
 | 
						seat->pressed.resize_edges = 0;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -820,6 +820,10 @@ view_destroy(struct view *view)
 | 
				
			||||||
		need_cursor_update = true;
 | 
							need_cursor_update = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server->seat.pressed.view == view) {
 | 
				
			||||||
 | 
							seat_reset_pressed(&server->seat);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	osd_on_view_destroy(view);
 | 
						osd_on_view_destroy(view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->scene_tree) {
 | 
						if (view->scene_tree) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue