diff --git a/AUTHORS b/AUTHORS index e69de29bb..9971ab08a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1 @@ +Havoc Pennington diff --git a/ChangeLog b/ChangeLog index 57d31a44b..e03998f11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2002-12-09 Havoc Pennington + + * AUTHORS: add myself here, bug #100789 + + * src/display.c (meta_display_set_grab_op_cursor): drop + PointerMotionHintMask + + * src/window.c (meta_window_handle_mouse_grab_op_event): don't use + XQueryPointer, as we aren't using PointerMotionHint now + + * src/display.c (event_callback): rearrange a bit of code + for slight speedup and clarity + + * src/window.c (update_resize) + (meta_window_handle_mouse_grab_op_event): implement + usage of the _METACITY_UPDATE_COUNTER + (meta_window_handle_mouse_grab_op_event): fix code that + used event->xbutton with a motion event + + * src/display.c (meta_display_open): add new atoms, and + initialize Xsync if we have it + (grab_op_is_resizing): new function + (meta_display_begin_grab_op): create an alarm monitoring + window's _METACITY_UPDATE_COUNTER + (meta_spew_event): conditionalize this on WITH_VERBOSE_MODE + and print alarm events. + + * src/window.c (meta_window_new): fetch _METACITY_UPDATE_COUNTER + + * configure.in (HAVE_XSYNC): check for Xsync extension + Mon Dec 9 22:09:56 2002 Soeren Sandmann * src/display.c, src/window.c: Handle crossing events during diff --git a/configure.in b/configure.in index 9755d6f28..e46659140 100644 --- a/configure.in +++ b/configure.in @@ -108,6 +108,8 @@ AC_ARG_ENABLE(sm, [ --disable-sm disable metacity's session m AC_ARG_ENABLE(startup-notification, [ --disable-startup-notification disable metacity's startup notification support, for embedded/size-sensitive custom non-GNOME builds],enable_startup_notification=no,enable_startup_notification=auto) +AC_ARG_ENABLE(xsync, [ --disable-xsync disable metacity's use of the XSync extension],enable_xsync=no,enable_xsync=auto) + ## try definining HAVE_BACKTRACE AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)]) @@ -231,7 +233,31 @@ if test "x$found_randr" = "xyes"; then AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) fi -METACITY_LIBS="$RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_LIBS" +XSYNC_LIBS= +found_xsync=no +AC_CHECK_LIB(Xext, XSyncQueryExtension, + [AC_CHECK_HEADER(X11/extensions/sync.h, + found_xsync=yes,, + [#include ])], + , $ALL_X_LIBS) + +if test x$enable_xsync = xno; then + found_xsync=no +fi + +if test x$enable_xsync = xyes; then + if test "$found_xsync" = "no"; then + AC_MSG_ERROR([--enable-xsync forced and XSync not found]) + exit 1 + fi +fi + +if test "x$found_xsync" = "xyes"; then + XSYNC_LIBS=-lXext + AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library]) +fi + +METACITY_LIBS="$XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_LIBS" METACITY_MESSAGE_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_MESSAGE_LIBS" METACITY_WINDOW_DEMO_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_WINDOW_DEMO_LIBS" METACITY_PROPS_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_PROPS_LIBS" @@ -338,5 +364,6 @@ metacity-$VERSION: Session management: ${found_sm} Shape extension: ${found_shape} Resize-and-rotate: ${found_randr} + Xsync: ${found_xsync} Deprecated config dialog: ${enable_config_dialog} " diff --git a/src/display.c b/src/display.c index 48a1b7797..18ea58a5d 100644 --- a/src/display.c +++ b/src/display.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2002 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -253,7 +254,9 @@ meta_display_open (const char *name) "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW", "_NET_STARTUP_ID", - "_METACITY_TOGGLE_VERBOSE" + "_METACITY_TOGGLE_VERBOSE", + "_METACITY_UPDATE_COUNTER", + "SYNC_COUNTER" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -389,6 +392,8 @@ meta_display_open (const char *name) display->atom_net_wm_state_below = atoms[76]; display->atom_net_startup_id = atoms[77]; display->atom_metacity_toggle_verbose = atoms[78]; + display->atom_metacity_update_counter = atoms[79]; + display->atom_sync_counter = atoms[80]; display->prop_hooks = NULL; meta_display_init_window_prop_hooks (display); @@ -453,6 +458,35 @@ meta_display_open (const char *name) display->grab_screen = NULL; display->grab_resize_popup = NULL; +#ifdef HAVE_XSYNC + { + int major, minor; + + display->xsync_error_base = 0; + display->xsync_event_base = 0; + + /* I don't think we really have to fill these in */ + major = SYNC_MAJOR_VERSION; + minor = SYNC_MINOR_VERSION; + + if (!XSyncQueryExtension (display->xdisplay, + &display->xsync_event_base, + &display->xsync_error_base) || + !XSyncInitialize (display->xdisplay, + &major, &minor)) + { + display->xsync_error_base = 0; + display->xsync_event_base = 0; + } + meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n", + major, minor, + display->xsync_error_base, + display->xsync_event_base); + } +#else /* HAVE_XSYNC */ + meta_verbose ("Not compiled with Xsync support\n"); +#endif /* !HAVE_XSYNC */ + screens = NULL; #ifdef HAVE_GTK_MULTIHEAD @@ -896,6 +930,51 @@ grab_op_is_keyboard (MetaGrabOp op) } } +gboolean +meta_grab_op_is_resizing (MetaGrabOp op) +{ + switch (op) + { + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_E: + case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: + case META_GRAB_OP_KEYBOARD_RESIZING_S: + case META_GRAB_OP_KEYBOARD_RESIZING_N: + case META_GRAB_OP_KEYBOARD_RESIZING_W: + case META_GRAB_OP_KEYBOARD_RESIZING_E: + case META_GRAB_OP_KEYBOARD_RESIZING_SE: + case META_GRAB_OP_KEYBOARD_RESIZING_NE: + case META_GRAB_OP_KEYBOARD_RESIZING_SW: + case META_GRAB_OP_KEYBOARD_RESIZING_NW: + return TRUE; + break; + + default: + return FALSE; + } +} + +gboolean +meta_grab_op_is_moving (MetaGrabOp op) +{ + switch (op) + { + case META_GRAB_OP_MOVING: + case META_GRAB_OP_KEYBOARD_MOVING: + return TRUE; + break; + + default: + return FALSE; + } +} + /* Get time of current event, or CurrentTime if none. */ guint32 meta_display_get_current_time (MetaDisplay *display) @@ -1093,6 +1172,20 @@ event_callback (XEvent *event, frame_was_receiver = TRUE; meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event\n"); } + +#ifdef HAVE_XSYNC + if (META_DISPLAY_HAS_XSYNC (display) && + event->type == (display->xsync_event_base + XSyncAlarmNotify) && + ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_update_alarm) + { + filter_out_event = TRUE; /* GTK doesn't want to see this really */ + + if (display->grab_op != META_GRAB_OP_NONE && + display->grab_window != NULL && + grab_op_is_mouse (display->grab_op)) + meta_window_handle_mouse_grab_op_event (display->grab_window, event); + } +#endif /* HAVE_XSYNC */ switch (event->type) { @@ -1242,25 +1335,22 @@ event_callback (XEvent *event, } break; case ButtonRelease: - if (grab_op_is_mouse (display->grab_op) && - display->grab_window == window) + if (display->grab_window == window && + grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case MotionNotify: - if (grab_op_is_mouse (display->grab_op) && - display->grab_window == window) + if (display->grab_window == window && + grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case EnterNotify: - if (grab_op_is_mouse (display->grab_op) && - display->grab_window == window) - { - meta_window_handle_mouse_grab_op_event (window, event); - break; - } + if (display->grab_window == window && + grab_op_is_mouse (display->grab_op)) + meta_window_handle_mouse_grab_op_event (window, event); /* do this even if window->has_focus to avoid races */ - if (window && !serial_is_ignored (display, event->xany.serial) && - event->xcrossing.detail != NotifyInferior) + else if (window && !serial_is_ignored (display, event->xany.serial) && + event->xcrossing.detail != NotifyInferior) { switch (meta_prefs_get_focus_mode ()) { @@ -1317,13 +1407,10 @@ event_callback (XEvent *event, } break; case LeaveNotify: - if (grab_op_is_mouse (display->grab_op) && - display->grab_window == window) - { - meta_window_handle_mouse_grab_op_event (window, event); - break; - } - if (window) + if (display->grab_window == window && + grab_op_is_mouse (display->grab_op)) + meta_window_handle_mouse_grab_op_event (window, event); + else if (window != NULL) { switch (meta_prefs_get_focus_mode ()) { @@ -1872,6 +1959,7 @@ event_get_time (MetaDisplay *display, } } +#ifdef WITH_VERBOSE_MODE const char* meta_event_detail_to_string (int d) { @@ -1908,7 +1996,9 @@ meta_event_detail_to_string (int d) return detail; } +#endif /* WITH_VERBOSE_MODE */ +#ifdef WITH_VERBOSE_MODE const char* meta_event_mode_to_string (int m) { @@ -1936,7 +2026,9 @@ meta_event_mode_to_string (int m) return mode; } +#endif /* WITH_VERBOSE_MODE */ +#ifdef WITH_VERBOSE_MODE static const char* stack_mode_to_string (int mode) { @@ -1956,7 +2048,9 @@ stack_mode_to_string (int mode) return "Unknown"; } +#endif /* WITH_VERBOSE_MODE */ +#ifdef WITH_VERBOSE_MODE static char* key_event_description (Display *xdisplay, XEvent *event) @@ -1971,7 +2065,43 @@ key_event_description (Display *xdisplay, return g_strdup_printf ("Key '%s' state 0x%x", str ? str : "(null)", event->xkey.state); } +#endif /* WITH_VERBOSE_MODE */ +#ifdef HAVE_XSYNC +#ifdef WITH_VERBOSE_MODE +static gint64 +sync_value_to_64 (const XSyncValue *value) +{ + gint64 v; + + v = XSyncValueLow32 (*value); + v |= (((gint64)XSyncValueHigh32 (*value)) << 32); + + return v; +} +#endif /* WITH_VERBOSE_MODE */ + +#ifdef WITH_VERBOSE_MODE +static const char* +alarm_state_to_string (XSyncAlarmState state) +{ + switch (state) + { + case XSyncAlarmActive: + return "Active"; + case XSyncAlarmInactive: + return "Inactive"; + case XSyncAlarmDestroyed: + return "Destroyed"; + default: + return "(unknown)"; + } +} +#endif /* WITH_VERBOSE_MODE */ + +#endif /* HAVE_XSYNC */ + +#ifdef WITH_VERBOSE_MODE static void meta_spew_event (MetaDisplay *display, XEvent *event) @@ -2207,8 +2337,30 @@ meta_spew_event (MetaDisplay *display, name = "MappingNotify"; break; default: - name = "(Unknown event)"; - extra = g_strdup_printf ("type: %d", event->xany.type); +#ifdef HAVE_XSYNC + if (META_DISPLAY_HAS_XSYNC (display) && + event->type == (display->xsync_event_base + XSyncAlarmNotify)) + { + XSyncAlarmNotifyEvent *aevent = (XSyncAlarmNotifyEvent*) event; + + name = "XSyncAlarmNotify"; + extra = + g_strdup_printf ("alarm: 0x%lx" + " counter_value: %" G_GINT64_FORMAT + " alarm_value: %" G_GINT64_FORMAT + " time: %u alarm state: %s", + aevent->alarm, + (gint64) sync_value_to_64 (&aevent->counter_value), + (gint64) sync_value_to_64 (&aevent->alarm_value), + (unsigned int) aevent->time, + alarm_state_to_string (aevent->state)); + } + else +#endif /* HAVE_XSYNC */ + { + name = "(Unknown event)"; + extra = g_strdup_printf ("type: %d", event->xany.type); + } break; } @@ -2230,6 +2382,7 @@ meta_spew_event (MetaDisplay *display, if (extra) g_free (extra); } +#endif /* WITH_VERBOSE_MODE */ MetaWindow* meta_display_lookup_x_window (MetaDisplay *display, @@ -2385,8 +2538,8 @@ meta_display_set_grab_op_cursor (MetaDisplay *display, cursor = xcursor_for_op (display, op); -#define GRAB_MASK (PointerMotionMask | PointerMotionHintMask | \ - ButtonPressMask | ButtonReleaseMask | \ +#define GRAB_MASK (PointerMotionMask | \ + ButtonPressMask | ButtonReleaseMask | \ EnterWindowMask | LeaveWindowMask) if (change_pointer) @@ -2515,9 +2668,14 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_initial_root_y = root_y; display->grab_current_root_x = root_x; display->grab_current_root_y = root_y; + display->grab_latest_motion_x = root_x; + display->grab_latest_motion_y = root_y; display->grab_last_moveresize_time.tv_sec = 0; display->grab_last_moveresize_time.tv_usec = 0; - +#ifdef HAVE_XSYNC + display->grab_update_alarm = None; +#endif + if (display->grab_window) { display->grab_initial_window_pos = display->grab_window->rect; @@ -2525,6 +2683,46 @@ meta_display_begin_grab_op (MetaDisplay *display, &display->grab_initial_window_pos.x, &display->grab_initial_window_pos.y); display->grab_current_window_pos = display->grab_initial_window_pos; + +#ifdef HAVE_XSYNC + if (meta_grab_op_is_resizing (display->grab_op) && + display->grab_window->update_counter != None) + { + XSyncAlarmAttributes values; + + /* trigger when we make a positive transition to a value + * one higher than the current value. + */ + values.trigger.counter = display->grab_window->update_counter; + values.trigger.value_type = XSyncRelative; + values.trigger.test_type = XSyncPositiveTransition; + XSyncIntToValue (&values.trigger.wait_value, 1); + + /* After triggering, increment test_value by this. + * (NOT wait_value above) + */ + XSyncIntToValue (&values.delta, 1); + + /* we want events (on by default anyway) */ + values.events = True; + + meta_error_trap_push_with_return (display); + display->grab_update_alarm = XSyncCreateAlarm (display->xdisplay, + XSyncCACounter | + XSyncCAValueType | + XSyncCAValue | + XSyncCATestType | + XSyncCADelta | + XSyncCAEvents, + &values); + if (meta_error_trap_pop_with_return (display, FALSE) != Success) + display->grab_update_alarm = None; + + meta_topic (META_DEBUG_RESIZING, + "Created update alarm 0x%lx\n", + display->grab_update_alarm); + } +#endif } meta_topic (META_DEBUG_WINDOW_OPS, @@ -2604,6 +2802,14 @@ meta_display_end_grab_op (MetaDisplay *display, else meta_screen_ungrab_all_keys (display->grab_screen); } + +#ifdef HAVE_XSYNC + if (display->grab_update_alarm != None) + { + XSyncDestroyAlarm (display->xdisplay, + display->grab_update_alarm); + } +#endif /* HAVE_XSYNC */ display->grab_window = NULL; display->grab_screen = NULL; diff --git a/src/display.h b/src/display.h index efd125cac..2641af4d5 100644 --- a/src/display.h +++ b/src/display.h @@ -2,6 +2,7 @@ /* * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2002 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -35,6 +36,10 @@ #include #endif +#ifdef HAVE_XSYNC +#include +#endif + #define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) /* this doesn't really belong here, oh well. */ @@ -162,6 +167,8 @@ struct _MetaDisplay Atom atom_net_wm_state_below; Atom atom_net_startup_id; Atom atom_metacity_toggle_verbose; + Atom atom_metacity_update_counter; + Atom atom_sync_counter; /* This is the actual window from focus events, * not the one we last set @@ -229,6 +236,8 @@ struct _MetaDisplay int grab_initial_root_y; int grab_current_root_x; int grab_current_root_y; + int grab_latest_motion_x; + int grab_latest_motion_y; gulong grab_mask; guint grab_have_pointer : 1; guint grab_have_keyboard : 1; @@ -236,7 +245,10 @@ struct _MetaDisplay MetaRectangle grab_current_window_pos; MetaResizePopup *grab_resize_popup; GTimeVal grab_last_moveresize_time; - +#ifdef HAVE_XSYNC + /* alarm monitoring client's _METACITY_UPDATE_COUNTER */ + XSyncAlarm grab_update_alarm; +#endif /* Keybindings stuff */ MetaKeyBinding *screen_bindings; @@ -275,11 +287,15 @@ struct _MetaDisplay MetaGroupPropHooks *group_prop_hooks; #ifdef HAVE_STARTUP_NOTIFICATION - /* This is at the end in case someone doesn't include config.h before this file - * the results won't be catastrophic - */ SnDisplay *sn_display; #endif +#ifdef HAVE_XSYNC + int xsync_event_base; + int xsync_error_base; +#define META_DISPLAY_HAS_XSYNC(display) ((display)->xsync_event_base != 0) +#else +#define META_DISPLAY_HAS_XSYNC(display) FALSE +#endif }; gboolean meta_display_open (const char *name); @@ -399,6 +415,9 @@ MetaWindow* meta_display_get_tab_current (MetaDisplay *display, int meta_resize_gravity_from_grab_op (MetaGrabOp op); +gboolean meta_grab_op_is_moving (MetaGrabOp op); +gboolean meta_grab_op_is_resizing (MetaGrabOp op); + gboolean meta_rectangle_intersect (MetaRectangle *src1, MetaRectangle *src2, MetaRectangle *dest); diff --git a/src/util.c b/src/util.c index 1d754422f..b54a66ce6 100644 --- a/src/util.c +++ b/src/util.c @@ -280,6 +280,8 @@ topic_name (MetaDebugTopic topic) return "PREFS"; case META_DEBUG_GROUPS: return "GROUPS"; + case META_DEBUG_RESIZING: + return "RESIZING"; } return "Window manager"; diff --git a/src/util.h b/src/util.h index 280e7eed8..abf29ea1e 100644 --- a/src/util.h +++ b/src/util.h @@ -64,7 +64,8 @@ typedef enum META_DEBUG_ERRORS = 1 << 14, META_DEBUG_STARTUP = 1 << 15, META_DEBUG_PREFS = 1 << 16, - META_DEBUG_GROUPS = 1 << 17 + META_DEBUG_GROUPS = 1 << 17, + META_DEBUG_RESIZING = 1 << 18 } MetaDebugTopic; diff --git a/src/window-props.c b/src/window-props.c index f1d19ce68..bcf639817 100644 --- a/src/window-props.c +++ b/src/window-props.c @@ -412,7 +412,32 @@ reload_net_startup_id (MetaWindow *window, window->desc); } -#define N_HOOKS 23 +static void +init_update_counter (MetaDisplay *display, + Atom property, + MetaPropValue *value) +{ + value->type = META_PROP_VALUE_SYNC_COUNTER; + value->atom = display->atom_metacity_update_counter; +} + +static void +reload_update_counter (MetaWindow *window, + MetaPropValue *value) +{ + if (value->type != META_PROP_VALUE_INVALID) + { +#ifdef HAVE_XSYNC + XSyncCounter counter = value->v.xcounter; + + window->update_counter = counter; + meta_verbose ("Window has _METACITY_UPDATE_COUNTER 0x%lx\n", + window->update_counter); +#endif + } +} + +#define N_HOOKS 24 void meta_display_init_window_prop_hooks (MetaDisplay *display) @@ -541,6 +566,11 @@ meta_display_init_window_prop_hooks (MetaDisplay *display) hooks[i].init_func = init_net_startup_id; hooks[i].reload_func = reload_net_startup_id; ++i; + + hooks[i].property = display->atom_metacity_update_counter; + hooks[i].init_func = init_update_counter; + hooks[i].reload_func = reload_update_counter; + ++i; if (i != N_HOOKS) g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS); diff --git a/src/window.c b/src/window.c index b5ac01570..a79e6001f 100644 --- a/src/window.c +++ b/src/window.c @@ -159,7 +159,7 @@ meta_window_new (MetaDisplay *display, GSList *tmp; MetaWorkspace *space; gulong existing_wm_state; -#define N_INITIAL_PROPS 9 +#define N_INITIAL_PROPS 10 Atom initial_props[N_INITIAL_PROPS]; int i; @@ -280,12 +280,16 @@ meta_window_new (MetaDisplay *display, window->dialog_pipe = -1; window->xwindow = xwindow; - + /* this is in window->screen->display, but that's too annoying to * type */ window->display = display; window->workspaces = NULL; + +#ifdef HAVE_XSYNC + window->update_counter = None; +#endif window->screen = NULL; tmp = display->screens; @@ -443,6 +447,7 @@ meta_window_new (MetaDisplay *display, initial_props[i++] = display->atom_net_wm_desktop; initial_props[i++] = display->atom_win_workspace; initial_props[i++] = display->atom_net_startup_id; + initial_props[i++] = display->atom_metacity_update_counter; g_assert (N_INITIAL_PROPS == i); meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS); @@ -4138,6 +4143,13 @@ process_property_notify (MetaWindow *window, meta_window_reload_property (window, window->display->atom_net_startup_id); } + else if (event->atom == window->display->atom_metacity_update_counter) + { + meta_verbose ("Property notify on %s for _METACITY_UPDATE_COUNTER\n", window->desc); + + meta_window_reload_property (window, + window->display->atom_metacity_update_counter); + } return TRUE; } @@ -6064,37 +6076,6 @@ meta_window_show_menu (MetaWindow *window, meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp); } -static gboolean -window_query_root_pointer (MetaWindow *window, - int *x, int *y) -{ - Window root_return, child_return; - int root_x_return, root_y_return; - int win_x_return, win_y_return; - unsigned int mask_return; - - meta_error_trap_push (window->display); - - XQueryPointer (window->display->xdisplay, - window->xwindow, - &root_return, - &child_return, - &root_x_return, - &root_y_return, - &win_x_return, - &win_y_return, - &mask_return); - - meta_error_trap_pop (window->display, TRUE); - - if (x) - *x = root_x_return; - if (y) - *y = root_y_return; - - return root_return == window->screen->xroot; -} - static void clear_moveresize_time (MetaWindow *window) { @@ -6108,6 +6089,7 @@ check_moveresize_frequency (MetaWindow *window) { GTimeVal current_time; double elapsed; + double max_resizes_per_second; g_get_current_time (¤t_time); @@ -6116,12 +6098,24 @@ check_moveresize_frequency (MetaWindow *window) ((((double)current_time.tv_sec - window->display->grab_last_moveresize_time.tv_sec) * G_USEC_PER_SEC + (current_time.tv_usec - window->display->grab_last_moveresize_time.tv_usec))) / 1000.0; -#define EPSILON (1e-6) -#define MAX_RESIZES_PER_SECOND 20.0 - if (elapsed >= 0.0 && elapsed < (1000.0 / MAX_RESIZES_PER_SECOND)) +#ifdef HAVE_XSYNC + if (window->display->grab_update_alarm != None) + max_resizes_per_second = 1.0; /* this is max resizes without + * getting any alarms; we resize + * immediately if we get one. + * i.e. this is a timeout for the + * client getting stuck. + */ + else +#endif /* HAVE_XSYNC */ + max_resizes_per_second = 20.0; + +#define EPSILON (1e-6) + if (elapsed >= 0.0 && elapsed < (1000.0 / max_resizes_per_second)) { - meta_verbose ("Delaying move/resize as only %g of %g seconds elapsed\n", - elapsed / 1000.0, 1.0 / MAX_RESIZES_PER_SECOND); + meta_topic (META_DEBUG_RESIZING, + "Delaying move/resize as only %g of %g seconds elapsed\n", + elapsed / 1000.0, 1.0 / max_resizes_per_second); return FALSE; } else if (elapsed < (0.0 - EPSILON)) /* handle clock getting set backward */ @@ -6129,9 +6123,10 @@ check_moveresize_frequency (MetaWindow *window) /* store latest time */ window->display->grab_last_moveresize_time = current_time; - - meta_verbose ("Doing move/resize as %g of %g seconds elapsed\n", - elapsed / 1000.0, 1.0 / MAX_RESIZES_PER_SECOND); + + meta_topic (META_DEBUG_RESIZING, + " Doing move/resize now (%g of %g seconds elapsed)\n", + elapsed / 1000.0, 1.0 / max_resizes_per_second); return TRUE; } @@ -6144,6 +6139,10 @@ update_move (MetaWindow *window, { int dx, dy; int new_x, new_y; + int move_threshold; + + window->display->grab_latest_motion_x = x; + window->display->grab_latest_motion_y = y; dx = x - window->display->grab_current_root_x; dy = y - window->display->grab_current_root_y; @@ -6161,9 +6160,14 @@ update_move (MetaWindow *window, /* Force a move regardless of time if a certain delta is exceeded, * so we don't get too out of sync with reality when dropping frames */ -#define MOVE_THRESHOLD 20 + /* FIXME this delta is all wrong, as it's absolute since + * the grab started. We want some sort of delta since + * we last sent a configure or something. + */ + move_threshold = 30; + if (!check_moveresize_frequency (window) && - ABS (dx) < MOVE_THRESHOLD && ABS (dy) < MOVE_THRESHOLD) + ABS (dx) < move_threshold && ABS (dy) < move_threshold) return; meta_window_move (window, TRUE, new_x, new_y); @@ -6176,6 +6180,11 @@ update_resize (MetaWindow *window, int dx, dy; int new_w, new_h; int gravity; + int resize_threshold; + MetaRectangle old; + + window->display->grab_latest_motion_x = x; + window->display->grab_latest_motion_y = y; dx = x - window->display->grab_current_root_x; dy = y - window->display->grab_current_root_y; @@ -6232,108 +6241,140 @@ update_resize (MetaWindow *window, /* Force a move regardless of time if a certain delta * is exceeded + * FIXME this delta is all wrong, as it's absolute since + * the grab started. We want some sort of delta since + * we last sent a configure or something. */ -#define RESIZE_THRESHOLD 20 +#ifdef HAVE_XSYNC + if (window->display->grab_update_alarm != None) + resize_threshold = 5000; /* disable */ + else +#endif /* HAVE_XSYNC */ + resize_threshold = 30; + if (!check_moveresize_frequency (window) && - ABS (dx) < RESIZE_THRESHOLD && ABS (dy) < RESIZE_THRESHOLD) + ABS (dx) < resize_threshold && ABS (dy) < resize_threshold) return; + + old = window->rect; /* compute gravity of client during operation */ gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); - + meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); + + /* If we don't actually resize the window, we clear the timestamp, + * so we'll quickly try again. Otherwise you get "stuck" because + * the window doesn't increment its _METACITY_UPDATE_COUNTER when + * nothing happens. + */ + if (window->rect.width == old.width && + window->rect.height == old.height) + clear_moveresize_time (window); } void meta_window_handle_mouse_grab_op_event (MetaWindow *window, XEvent *event) { +#ifdef HAVE_XSYNC + if (event->type == (window->display->xsync_event_base + XSyncAlarmNotify)) + { + meta_topic (META_DEBUG_RESIZING, + "Alarm event received last motion x = %d y = %d\n", + window->display->grab_latest_motion_x, + window->display->grab_latest_motion_y); + + /* This means we are ready for another configure. */ + switch (window->display->grab_op) + { + case META_GRAB_OP_RESIZING_E: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + case META_GRAB_OP_KEYBOARD_RESIZING_S: + case META_GRAB_OP_KEYBOARD_RESIZING_N: + case META_GRAB_OP_KEYBOARD_RESIZING_W: + case META_GRAB_OP_KEYBOARD_RESIZING_E: + case META_GRAB_OP_KEYBOARD_RESIZING_SE: + case META_GRAB_OP_KEYBOARD_RESIZING_NE: + case META_GRAB_OP_KEYBOARD_RESIZING_SW: + case META_GRAB_OP_KEYBOARD_RESIZING_NW: + clear_moveresize_time (window); /* force update to do something */ + + /* no pointer round trip here, to keep in sync */ + update_resize (window, + window->display->grab_latest_motion_x, + window->display->grab_latest_motion_y); + break; + + default: + break; + } + } +#endif /* HAVE_XSYNC */ + switch (event->type) { case ButtonRelease: - switch (window->display->grab_op) + if (meta_grab_op_is_moving (window->display->grab_op)) { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_KEYBOARD_MOVING: clear_moveresize_time (window); if (event->xbutton.root == window->screen->xroot) update_move (window, event->xbutton.state, event->xbutton.x_root, event->xbutton.y_root); - break; - - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: + } + else if (meta_grab_op_is_resizing (window->display->grab_op)) + { clear_moveresize_time (window); if (event->xbutton.root == window->screen->xroot) update_resize (window, event->xbutton.x_root, event->xbutton.y_root); - break; - - default: - break; } meta_display_end_grab_op (window->display, event->xbutton.time); - break; - - case EnterNotify: - case LeaveNotify: + break; + case MotionNotify: - switch (window->display->grab_op) + if (meta_grab_op_is_moving (window->display->grab_op)) { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_KEYBOARD_MOVING: - { - int x, y; - if (window_query_root_pointer (window, &x, &y)) - update_move (window, - event->xbutton.state, - x, y); - } - break; - - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - { - int x, y; - if (window_query_root_pointer (window, &x, &y)) - update_resize (window, x, y); - } - break; - - default: - break; + if (event->xmotion.root == window->screen->xroot) + update_move (window, + event->xmotion.state, + event->xmotion.x_root, + event->xmotion.y_root); + } + else if (meta_grab_op_is_resizing (window->display->grab_op)) + { + if (event->xmotion.root == window->screen->xroot) + update_resize (window, + event->xmotion.x_root, + event->xmotion.y_root); } break; + case EnterNotify: + case LeaveNotify: + if (meta_grab_op_is_moving (window->display->grab_op)) + { + if (event->xcrossing.root == window->screen->xroot) + update_move (window, + event->xcrossing.state, + event->xcrossing.x_root, + event->xcrossing.y_root); + } + else if (meta_grab_op_is_resizing (window->display->grab_op)) + { + if (event->xcrossing.root == window->screen->xroot) + update_resize (window, + event->xcrossing.x_root, + event->xcrossing.y_root); + } + break; default: break; } @@ -6711,9 +6752,7 @@ meta_window_update_resize_grab_op (MetaWindow *window, window->display->grab_current_root_y = y + y_offset; if (window->display->grab_window) - { - window->display->grab_current_window_pos = window->rect; - } + window->display->grab_current_window_pos = window->rect; if (update_cursor) { diff --git a/src/window.h b/src/window.h index 21c71179b..c200c9c82 100644 --- a/src/window.h +++ b/src/window.h @@ -2,6 +2,7 @@ /* * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2002 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,6 +23,7 @@ #ifndef META_WINDOW_H #define META_WINDOW_H +#include #include "screen.h" #include "util.h" #include "stack.h" @@ -216,6 +218,11 @@ struct _MetaWindow /* Info on which props we got our attributes from */ guint using_net_wm_name : 1; /* vs. plain wm_name */ guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */ + +#ifdef HAVE_XSYNC + /* XSync update counter */ + XSyncCounter update_counter; +#endif /* Number of UnmapNotify that are caused by us, if * we get UnmapNotify with none pending then the client diff --git a/src/xprops.c b/src/xprops.c index 4f92e2d48..f903b1e60 100644 --- a/src/xprops.c +++ b/src/xprops.c @@ -505,6 +505,24 @@ window_from_results (GetPropertyResults *results, return TRUE; } +#ifdef HAVE_XSYNC +static gboolean +counter_from_results (GetPropertyResults *results, + XSyncCounter *counter_p) +{ + if (!validate_or_free_results (results, 32, + results->display->atom_sync_counter, + TRUE)) + return FALSE; + + *counter_p = *(XSyncCounter*) results->prop; + XFree (results->prop); + results->prop = NULL; + + return TRUE; +} +#endif + gboolean meta_prop_get_window (MetaDisplay *display, Window xwindow, @@ -915,6 +933,9 @@ meta_prop_get_values (MetaDisplay *display, case META_PROP_VALUE_SIZE_HINTS: values[i].required_type = XA_WM_SIZE_HINTS; break; + case META_PROP_VALUE_SYNC_COUNTER: + values[i].required_type = display->atom_sync_counter; + break; } } @@ -1042,6 +1063,15 @@ meta_prop_get_values (MetaDisplay *display, &values[i].v.size_hints.flags)) values[i].type = META_PROP_VALUE_INVALID; break; + case META_PROP_VALUE_SYNC_COUNTER: +#ifdef HAVE_XSYNC + if (!counter_from_results (&results, + &values[i].v.xcounter)) + values[i].type = META_PROP_VALUE_INVALID; +#else + values[i].type = META_PROP_VALUE_INVALID; +#endif + break; } next: @@ -1093,6 +1123,8 @@ free_value (MetaPropValue *value) case META_PROP_VALUE_CARDINAL_LIST: meta_XFree (value->v.cardinal_list.cardinals); break; + case META_PROP_VALUE_SYNC_COUNTER: + break; } } diff --git a/src/xprops.h b/src/xprops.h index a1c6adfd3..24180ee6f 100644 --- a/src/xprops.h +++ b/src/xprops.h @@ -22,6 +22,7 @@ #ifndef META_XPROPS_H #define META_XPROPS_H +#include #include "display.h" #include @@ -142,7 +143,8 @@ typedef enum META_PROP_VALUE_TEXT_PROPERTY, /* comes back as UTF-8 string */ META_PROP_VALUE_WM_HINTS, META_PROP_VALUE_CLASS_HINT, - META_PROP_VALUE_SIZE_HINTS + META_PROP_VALUE_SIZE_HINTS, + META_PROP_VALUE_SYNC_COUNTER } MetaPropValueType; /* used to request/return/store property values */ @@ -160,6 +162,9 @@ typedef struct gulong cardinal; XWMHints *wm_hints; XClassHint class_hint; +#ifdef HAVE_XSYNC + XSyncCounter xcounter; +#endif struct {