mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
window: Update drag hotspot as new touches approach
Any number of touches >= 3 starts a drag operation, but the window jumped around as new touches joined. So recalculate the touch drag area/hotspot and tiling mode as expected as soon as touches enter/leave the drag op.
This commit is contained in:
parent
141a353a52
commit
bdfb8609a3
@ -160,6 +160,7 @@ struct _MetaTouchInfo
|
|||||||
gdouble initial_root_y;
|
gdouble initial_root_y;
|
||||||
|
|
||||||
guint notified : 1;
|
guint notified : 1;
|
||||||
|
guint use_for_hotspot : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaDisplay
|
struct _MetaDisplay
|
||||||
|
@ -329,6 +329,9 @@ struct _MetaWindow
|
|||||||
/* if TRUE, window didn't yet get the FocusIn for window->focus_keyboard */
|
/* if TRUE, window didn't yet get the FocusIn for window->focus_keyboard */
|
||||||
guint expecting_focus_in : 1;
|
guint expecting_focus_in : 1;
|
||||||
|
|
||||||
|
/* if TRUE, tiling mode is held regardless of newer touch updates */
|
||||||
|
guint touch_hold_tiling_mode : 1;
|
||||||
|
|
||||||
/* Keyboard currently owning the window focus, or NULL */
|
/* Keyboard currently owning the window focus, or NULL */
|
||||||
MetaDevice *focus_keyboard;
|
MetaDevice *focus_keyboard;
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@
|
|||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define N_TOUCHES_FOR_GRAB 3
|
||||||
|
#define TOUCH_THRESHOLD 16
|
||||||
|
#define TILING_ZOOM_FACTOR 1.5
|
||||||
|
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
static int destroying_windows_disallowed = 0;
|
static int destroying_windows_disallowed = 0;
|
||||||
@ -8659,23 +8663,26 @@ update_move (MetaWindow *window,
|
|||||||
y >= monitor->rect.y && y <= work_area.y)
|
y >= monitor->rect.y && y <= work_area.y)
|
||||||
window->tile_mode = META_TILE_MAXIMIZED;
|
window->tile_mode = META_TILE_MAXIMIZED;
|
||||||
else if (window->cur_touches &&
|
else if (window->cur_touches &&
|
||||||
g_hash_table_size (window->cur_touches) == 3)
|
g_hash_table_size (window->cur_touches) >= N_TOUCHES_FOR_GRAB)
|
||||||
{
|
{
|
||||||
window->tile_mode = META_TILE_NONE;
|
if (!window->touch_hold_tiling_mode)
|
||||||
|
|
||||||
if (window->cur_touch_area_height >
|
|
||||||
window->initial_touch_area_height * 1.5)
|
|
||||||
{
|
{
|
||||||
if (window->cur_touch_area_width >
|
window->tile_mode = META_TILE_NONE;
|
||||||
window->initial_touch_area_width * 1.5 &&
|
|
||||||
meta_window_can_tile_maximized (window))
|
if (window->cur_touch_area_height >
|
||||||
window->tile_mode = META_TILE_MAXIMIZED;
|
window->initial_touch_area_height * TILING_ZOOM_FACTOR)
|
||||||
else if (meta_window_can_tile_side_by_side (window, device))
|
|
||||||
{
|
{
|
||||||
if (x < (monitor->rect.x + (monitor->rect.width / 2)))
|
if (window->cur_touch_area_width >
|
||||||
window->tile_mode = META_TILE_LEFT;
|
window->initial_touch_area_width * TILING_ZOOM_FACTOR &&
|
||||||
else
|
meta_window_can_tile_maximized (window))
|
||||||
window->tile_mode = META_TILE_RIGHT;
|
window->tile_mode = META_TILE_MAXIMIZED;
|
||||||
|
else if (meta_window_can_tile_side_by_side (window, device))
|
||||||
|
{
|
||||||
|
if (x < (monitor->rect.x + (monitor->rect.width / 2)))
|
||||||
|
window->tile_mode = META_TILE_LEFT;
|
||||||
|
else
|
||||||
|
window->tile_mode = META_TILE_RIGHT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10808,6 +10815,7 @@ typedef struct
|
|||||||
gdouble top_left_y;
|
gdouble top_left_y;
|
||||||
gdouble bottom_right_x;
|
gdouble bottom_right_x;
|
||||||
gdouble bottom_right_y;
|
gdouble bottom_right_y;
|
||||||
|
gboolean only_hotspot;
|
||||||
} BoundingRectCoords;
|
} BoundingRectCoords;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -10818,6 +10826,10 @@ calculate_touch_bounding_rect (gpointer key,
|
|||||||
BoundingRectCoords *bounding_rect = user_data;
|
BoundingRectCoords *bounding_rect = user_data;
|
||||||
MetaTouchInfo *touch_info = value;
|
MetaTouchInfo *touch_info = value;
|
||||||
|
|
||||||
|
if (bounding_rect->only_hotspot &&
|
||||||
|
!touch_info->use_for_hotspot)
|
||||||
|
return;
|
||||||
|
|
||||||
if (touch_info->root_x < bounding_rect->top_left_x)
|
if (touch_info->root_x < bounding_rect->top_left_x)
|
||||||
bounding_rect->top_left_x = touch_info->root_x;
|
bounding_rect->top_left_x = touch_info->root_x;
|
||||||
if (touch_info->root_x > bounding_rect->bottom_right_x)
|
if (touch_info->root_x > bounding_rect->bottom_right_x)
|
||||||
@ -10829,6 +10841,55 @@ calculate_touch_bounding_rect (gpointer key,
|
|||||||
bounding_rect->bottom_right_y = touch_info->root_y;
|
bounding_rect->bottom_right_y = touch_info->root_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
window_get_touch_area (MetaWindow *window,
|
||||||
|
gdouble *center_x,
|
||||||
|
gdouble *center_y,
|
||||||
|
gdouble *width,
|
||||||
|
gdouble *height)
|
||||||
|
{
|
||||||
|
if (g_hash_table_size (window->cur_touches) == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (width || height)
|
||||||
|
{
|
||||||
|
BoundingRectCoords bounding_rect = { DBL_MAX, DBL_MAX,
|
||||||
|
DBL_MIN, DBL_MIN,
|
||||||
|
FALSE };
|
||||||
|
|
||||||
|
g_hash_table_foreach (window->cur_touches,
|
||||||
|
calculate_touch_bounding_rect,
|
||||||
|
&bounding_rect);
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = bounding_rect.bottom_right_x - bounding_rect.top_left_x;
|
||||||
|
if (height)
|
||||||
|
*height = bounding_rect.bottom_right_y - bounding_rect.top_left_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (center_x || center_y)
|
||||||
|
{
|
||||||
|
gdouble w, h;
|
||||||
|
BoundingRectCoords bounding_rect = { DBL_MAX, DBL_MAX,
|
||||||
|
DBL_MIN, DBL_MIN,
|
||||||
|
TRUE };
|
||||||
|
|
||||||
|
g_hash_table_foreach (window->cur_touches,
|
||||||
|
calculate_touch_bounding_rect,
|
||||||
|
&bounding_rect);
|
||||||
|
|
||||||
|
w = bounding_rect.bottom_right_x - bounding_rect.top_left_x;
|
||||||
|
h = bounding_rect.bottom_right_y - bounding_rect.top_left_y;
|
||||||
|
|
||||||
|
if (center_x)
|
||||||
|
*center_x = bounding_rect.top_left_x + (w / 2);
|
||||||
|
if (center_y)
|
||||||
|
*center_y = bounding_rect.top_left_y + (h / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_touch (MetaWindow *window,
|
notify_touch (MetaWindow *window,
|
||||||
MetaDevice *source,
|
MetaDevice *source,
|
||||||
@ -10904,6 +10965,8 @@ meta_window_update_touch (MetaWindow *window,
|
|||||||
touch_info = g_slice_new (MetaTouchInfo);
|
touch_info = g_slice_new (MetaTouchInfo);
|
||||||
touch_info->initial_root_x = root_x;
|
touch_info->initial_root_x = root_x;
|
||||||
touch_info->initial_root_y = root_y;
|
touch_info->initial_root_y = root_y;
|
||||||
|
touch_info->use_for_hotspot =
|
||||||
|
(g_hash_table_size (window->cur_touches) < N_TOUCHES_FOR_GRAB);
|
||||||
|
|
||||||
g_hash_table_insert (window->cur_touches,
|
g_hash_table_insert (window->cur_touches,
|
||||||
GUINT_TO_POINTER (touch_id),
|
GUINT_TO_POINTER (touch_id),
|
||||||
@ -10916,9 +10979,9 @@ meta_window_update_touch (MetaWindow *window,
|
|||||||
|
|
||||||
n_touches = g_hash_table_size (window->cur_touches);
|
n_touches = g_hash_table_size (window->cur_touches);
|
||||||
|
|
||||||
if (!new_touch && n_touches < 3 &&
|
if (!new_touch && n_touches < N_TOUCHES_FOR_GRAB &&
|
||||||
(ABS (touch_info->initial_root_x - touch_info->root_x) >= 16 ||
|
(ABS (touch_info->initial_root_x - touch_info->root_x) >= TOUCH_THRESHOLD ||
|
||||||
ABS (touch_info->initial_root_y - touch_info->root_y) >= 16))
|
ABS (touch_info->initial_root_y - touch_info->root_y) >= TOUCH_THRESHOLD))
|
||||||
{
|
{
|
||||||
/* There aren't yet enough touches on the window to trigger
|
/* There aren't yet enough touches on the window to trigger
|
||||||
* window moving, and one of the touches moved past the
|
* window moving, and one of the touches moved past the
|
||||||
@ -10929,13 +10992,11 @@ meta_window_update_touch (MetaWindow *window,
|
|||||||
notify_touch_events (window, source, FALSE);
|
notify_touch_events (window, source, FALSE);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (n_touches >= 3)
|
else if (n_touches >= N_TOUCHES_FOR_GRAB)
|
||||||
{
|
{
|
||||||
gdouble x, y, width, height;
|
gdouble center_x, center_y, width, height;
|
||||||
BoundingRectCoords bounding_rect = { DBL_MAX, DBL_MAX,
|
|
||||||
DBL_MIN, DBL_MIN };
|
|
||||||
|
|
||||||
if (n_touches == 3 && new_touch)
|
if (n_touches == N_TOUCHES_FOR_GRAB && new_touch)
|
||||||
{
|
{
|
||||||
/* Accept all touches for the move operation */
|
/* Accept all touches for the move operation */
|
||||||
notify_touch_events (window, source, TRUE);
|
notify_touch_events (window, source, TRUE);
|
||||||
@ -10948,21 +11009,24 @@ meta_window_update_touch (MetaWindow *window,
|
|||||||
touch_info->notified = TRUE;
|
touch_info->notified = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_foreach (window->cur_touches,
|
/* Set grab x/y coordinates at the middle of the bounding box,
|
||||||
calculate_touch_bounding_rect,
|
|
||||||
&bounding_rect);
|
|
||||||
|
|
||||||
/* Get x/y coordinates at the middle of the bounding box,
|
|
||||||
* this will be the hotspot for the window moving operation
|
* this will be the hotspot for the window moving operation
|
||||||
*/
|
*/
|
||||||
width = bounding_rect.bottom_right_x - bounding_rect.top_left_x;
|
window_get_touch_area (window, ¢er_x, ¢er_y, &width, &height);
|
||||||
height = bounding_rect.bottom_right_y - bounding_rect.top_left_y;
|
window->cur_touch_area_width = width;
|
||||||
x = bounding_rect.top_left_x + (width / 2);
|
window->cur_touch_area_height = height;
|
||||||
y = bounding_rect.top_left_y + (height / 2);
|
|
||||||
|
|
||||||
if (new_touch)
|
if (new_touch)
|
||||||
{
|
{
|
||||||
if (n_touches == 3)
|
window->touch_hold_tiling_mode = FALSE;
|
||||||
|
|
||||||
|
/* (re)set initial bounding box
|
||||||
|
* so the new touch is included
|
||||||
|
*/
|
||||||
|
window->initial_touch_area_width = width;
|
||||||
|
window->initial_touch_area_height = height;
|
||||||
|
|
||||||
|
if (n_touches == N_TOUCHES_FOR_GRAB)
|
||||||
{
|
{
|
||||||
/* Start window move operation with the
|
/* Start window move operation with the
|
||||||
* bounding rectangle center as the hotspot
|
* bounding rectangle center as the hotspot
|
||||||
@ -10975,18 +11039,37 @@ meta_window_update_touch (MetaWindow *window,
|
|||||||
TRUE, FALSE,
|
TRUE, FALSE,
|
||||||
1, 0,
|
1, 0,
|
||||||
evtime,
|
evtime,
|
||||||
x, y);
|
center_x, center_y);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Update hotspot for grab */
|
||||||
|
window->cur_grab->grab_anchor_root_x = center_x;
|
||||||
|
window->cur_grab->grab_anchor_root_y = center_y;
|
||||||
|
window->cur_grab->grab_latest_motion_x = center_x;
|
||||||
|
window->cur_grab->grab_latest_motion_y = center_y;
|
||||||
|
meta_window_get_client_root_coords (window,
|
||||||
|
&window->cur_grab->grab_anchor_window_pos);
|
||||||
|
|
||||||
window->initial_touch_area_width = width;
|
/* Update window, and tiling mode */
|
||||||
window->initial_touch_area_height = height;
|
update_move (window, device, FALSE, center_x, center_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (window->cur_grab)
|
else if (window->cur_grab)
|
||||||
{
|
{
|
||||||
window->cur_touch_area_width = width;
|
/* Unset tiling mode as the remaining touches moved past the threshold */
|
||||||
window->cur_touch_area_height = height;
|
if (window->touch_hold_tiling_mode &&
|
||||||
|
((window->cur_touch_area_width >
|
||||||
|
(window->initial_touch_area_width + (2 * TOUCH_THRESHOLD))) ||
|
||||||
|
(window->cur_touch_area_height >
|
||||||
|
(window->initial_touch_area_height + (2 * TOUCH_THRESHOLD))) ||
|
||||||
|
(ABS (window->cur_grab->grab_anchor_root_x -
|
||||||
|
window->cur_grab->grab_latest_motion_x) > TOUCH_THRESHOLD) ||
|
||||||
|
(ABS (window->cur_grab->grab_anchor_root_y -
|
||||||
|
window->cur_grab->grab_latest_motion_y) > TOUCH_THRESHOLD)))
|
||||||
|
window->touch_hold_tiling_mode = FALSE;
|
||||||
|
|
||||||
update_move (window, device, FALSE, x, y);
|
update_move (window, device, FALSE, center_x, center_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -11002,6 +11085,7 @@ meta_window_end_touch (MetaWindow *window,
|
|||||||
MetaTouchInfo *info;
|
MetaTouchInfo *info;
|
||||||
MetaDevice *source;
|
MetaDevice *source;
|
||||||
guint touch_id, n_touches;
|
guint touch_id, n_touches;
|
||||||
|
MetaDevice *device;
|
||||||
Time evtime;
|
Time evtime;
|
||||||
|
|
||||||
meta_input_event_get_touch_id (window->display, event, &touch_id);
|
meta_input_event_get_touch_id (window->display, event, &touch_id);
|
||||||
@ -11023,17 +11107,42 @@ meta_window_end_touch (MetaWindow *window,
|
|||||||
GUINT_TO_POINTER (touch_id));
|
GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
n_touches = g_hash_table_size (window->cur_touches);
|
n_touches = g_hash_table_size (window->cur_touches);
|
||||||
|
device = meta_input_event_get_device (window->display, event);
|
||||||
|
|
||||||
window->initial_touch_area_width = 0;
|
if (n_touches >= N_TOUCHES_FOR_GRAB)
|
||||||
window->initial_touch_area_height = 0;
|
|
||||||
window->cur_touch_area_width = 0;
|
|
||||||
window->cur_touch_area_height = 0;
|
|
||||||
|
|
||||||
if (n_touches == 2)
|
|
||||||
{
|
{
|
||||||
MetaDevice *device;
|
gdouble center_x, center_y, width, height;
|
||||||
|
|
||||||
|
window_get_touch_area (window, ¢er_x, ¢er_y, &width, &height);
|
||||||
|
|
||||||
|
window->initial_touch_area_width = width;
|
||||||
|
window->initial_touch_area_height = height;
|
||||||
|
window->cur_touch_area_width = width;
|
||||||
|
window->cur_touch_area_height = height;
|
||||||
|
|
||||||
|
/* Update hotspot to the new bounding box center */
|
||||||
|
window->cur_grab->grab_anchor_root_x = center_x;
|
||||||
|
window->cur_grab->grab_anchor_root_y = center_y;
|
||||||
|
window->cur_grab->grab_latest_motion_x = center_x;
|
||||||
|
window->cur_grab->grab_latest_motion_y = center_y;
|
||||||
|
meta_window_get_client_root_coords (window,
|
||||||
|
&window->cur_grab->grab_anchor_window_pos);
|
||||||
|
|
||||||
|
/* Hold tiling mode until the remaining
|
||||||
|
* touches moved past some threshold
|
||||||
|
*/
|
||||||
|
window->touch_hold_tiling_mode = TRUE;
|
||||||
|
|
||||||
|
update_move (window, device, FALSE, center_x, center_y);
|
||||||
|
}
|
||||||
|
else if (n_touches == N_TOUCHES_FOR_GRAB - 1)
|
||||||
|
{
|
||||||
|
/* We just lost the last touch to hold the grab */
|
||||||
|
window->initial_touch_area_width = 0;
|
||||||
|
window->initial_touch_area_height = 0;
|
||||||
|
window->cur_touch_area_width = 0;
|
||||||
|
window->cur_touch_area_height = 0;
|
||||||
|
|
||||||
device = meta_input_event_get_device (window->display, event);
|
|
||||||
meta_display_end_grab_op (window->display, device, evtime);
|
meta_display_end_grab_op (window->display, device, evtime);
|
||||||
}
|
}
|
||||||
else if (n_touches == 0 &&
|
else if (n_touches == 0 &&
|
||||||
|
Loading…
Reference in New Issue
Block a user