EAPI Ecore_X_Sync_Alarm ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter) { Ecore_X_Sync_Alarm alarm; XSyncAlarmAttributes values; XSyncValue init; LOGFN(__FILE__, __LINE__, __FUNCTION__); XSyncIntToValue(&init, 0); XSyncSetCounter(_ecore_x_disp, counter, init); values.trigger.counter = counter; values.trigger.value_type = XSyncAbsolute; XSyncIntToValue(&values.trigger.wait_value, 1); values.trigger.test_type = XSyncPositiveComparison; XSyncIntToValue(&values.delta, 1); values.events = True; alarm = XSyncCreateAlarm(_ecore_x_disp, XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCADelta | XSyncCAEvents, &values); ecore_x_sync(); return alarm; } /* ecore_x_sync_alarm_new */
static MetaSync * meta_sync_new (Display *xdisplay) { MetaSync *self; XSyncAlarmAttributes attrs; self = g_malloc0 (sizeof (MetaSync)); self->xdisplay = xdisplay; self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE); self->gl_x11_sync = 0; self->gpu_fence = 0; self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO); attrs.trigger.counter = self->xcounter; attrs.trigger.value_type = XSyncAbsolute; attrs.trigger.wait_value = SYNC_VALUE_ONE; attrs.trigger.test_type = XSyncPositiveTransition; attrs.events = TRUE; self->xalarm = XSyncCreateAlarm (xdisplay, XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCAEvents, &attrs); XSyncIntToValue (&self->next_counter_value, 1); self->state = META_SYNC_STATE_READY; return self; }
gboolean meta_sync_ring_init (Display *xdisplay) { gint major, minor; guint i; MetaSyncRing *ring = meta_sync_ring_get (); if (!ring) return FALSE; g_return_val_if_fail (xdisplay != NULL, FALSE); g_return_val_if_fail (ring->xdisplay == NULL, FALSE); if (!load_required_symbols ()) return FALSE; if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) || !XSyncInitialize (xdisplay, &major, &minor)) return FALSE; XSyncIntToValue (&SYNC_VALUE_ZERO, 0); XSyncIntToValue (&SYNC_VALUE_ONE, 1); ring->xdisplay = xdisplay; ring->alarm_to_sync = g_hash_table_new (NULL, NULL); for (i = 0; i < NUM_SYNCS; ++i) { MetaSync *sync = meta_sync_new (ring->xdisplay); ring->syncs_array[i] = sync; g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync); } /* Since the connection we create the X fences on isn't the same as * the one used for the GLX context, we need to XSync() here to * ensure glImportSync() succeeds. */ XSync (xdisplay, False); for (i = 0; i < NUM_SYNCS; ++i) meta_sync_import (ring->syncs_array[i]); ring->current_sync_idx = 0; ring->current_sync = ring->syncs_array[0]; ring->warmup_syncs = 0; return TRUE; }
EAPI void ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, int val) { XSyncWaitCondition cond; XSyncValue v, v2; LOGFN(__FILE__, __LINE__, __FUNCTION__); XSyncQueryCounter(_ecore_x_disp, counter, &v); XSyncIntToValue(&v, val); XSyncIntToValue(&v2, val + 1); cond.trigger.counter = counter; cond.trigger.value_type = XSyncAbsolute; cond.trigger.wait_value = v; cond.trigger.test_type = XSyncPositiveComparison; cond.event_threshold = v2; XSyncAwait(_ecore_x_disp, &cond, 1); // XSync(_ecore_x_disp, False); // dont need this } /* ecore_x_sync_counter_val_wait */
EAPI void ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, int by) { XSyncValue v; LOGFN(__FILE__, __LINE__, __FUNCTION__); XSyncIntToValue(&v, by); XSyncChangeCounter(_ecore_x_disp, counter, v); } /* ecore_x_sync_counter_inc */
EAPI void ecore_x_sync_counter_set(Ecore_X_Sync_Counter counter, int val) { XSyncValue v; LOGFN(__FILE__, __LINE__, __FUNCTION__); XSyncIntToValue(&v, val); XSyncSetCounter(_ecore_x_disp, counter, v); }
EAPI Ecore_X_Sync_Counter ecore_x_sync_counter_new(int val) { XSyncCounter counter; XSyncValue v; LOGFN(__FILE__, __LINE__, __FUNCTION__); XSyncIntToValue(&v, val); counter = XSyncCreateCounter(_ecore_x_disp, v); return counter; } /* ecore_x_sync_counter_new */
static AsyncWaiter * async_waiter_new (void) { AsyncWaiter *waiter = g_new0 (AsyncWaiter, 1); Display *xdisplay = meta_get_display ()->xdisplay; XSyncValue value; XSyncAlarmAttributes attr; waiter->counter_value = 0; XSyncIntToValue (&value, waiter->counter_value); waiter->counter = XSyncCreateCounter (xdisplay, value); attr.trigger.counter = waiter->counter; attr.trigger.test_type = XSyncPositiveComparison; /* Initialize to one greater than the current value */ attr.trigger.value_type = XSyncRelative; XSyncIntToValue (&attr.trigger.wait_value, 1); /* After triggering, increment test_value by this until * until the test condition is false */ XSyncIntToValue (&attr.delta, 1); /* we want events (on by default anyway) */ attr.events = True; waiter->alarm = XSyncCreateAlarm (xdisplay, XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCADelta | XSyncCAEvents, &attr); waiter->loop = g_main_loop_new (NULL, FALSE); return waiter; }
static void async_waiter_set_and_wait (AsyncWaiter *waiter) { Display *xdisplay = meta_get_display ()->xdisplay; int wait_value = async_waiter_next_value (waiter); XSyncValue sync_value; XSyncIntToValue (&sync_value, wait_value); XSyncSetCounter (xdisplay, waiter->counter, sync_value); async_waiter_wait (waiter, wait_value); }
static void do_resize(void) { gint x, y, w, h, lw, lh; /* see if it is actually going to resize USE cur_x AND cur_y HERE ! Otherwise the try_configure won't know what struts to use !! */ x = cur_x; y = cur_y; w = cur_w; h = cur_h; client_try_configure(moveresize_client, &x, &y, &w, &h, &lw, &lh, TRUE); if (!(w == moveresize_client->area.width && h == moveresize_client->area.height) && /* if waiting_for_sync == 0, then we aren't waiting. if it is > SYNC_TIMEOUTS, then we have timed out that many times already, so forget about waiting more */ (waiting_for_sync == 0 || waiting_for_sync > SYNC_TIMEOUTS)) { #ifdef SYNC if (config_resize_redraw && obt_display_extension_sync && /* don't send another sync when one is pending */ waiting_for_sync == 0 && moveresize_client->sync_request && moveresize_client->sync_counter && !moveresize_client->not_responding) { XEvent ce; XSyncValue val; /* increment the value we're waiting for */ ++moveresize_client->sync_counter_value; XSyncIntToValue(&val, moveresize_client->sync_counter_value); /* tell the client what we're waiting for */ ce.xclient.type = ClientMessage; ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS); ce.xclient.display = obt_display; ce.xclient.window = moveresize_client->window; ce.xclient.format = 32; ce.xclient.data.l[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST); ce.xclient.data.l[1] = event_time(); ce.xclient.data.l[2] = XSyncValueLow32(val); ce.xclient.data.l[3] = XSyncValueHigh32(val); ce.xclient.data.l[4] = 0l; XSendEvent(obt_display, moveresize_client->window, FALSE, NoEventMask, &ce); waiting_for_sync = 1; if (sync_timer) g_source_remove(sync_timer); sync_timer = g_timeout_add(2000, sync_timeout_func, NULL); } #endif /* force a ConfigureNotify, it is part of the spec for SYNC resizing and MUST follow the sync counter notification */ client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h, TRUE, FALSE, TRUE); } /* this would be better with a fixed width font ... XXX can do it better if there are 2 text boxes */ if (config_resize_popup_show == 2 || /* == "Always" */ (config_resize_popup_show == 1 && /* == "Nonpixel" */ moveresize_client->size_inc.width > 1 && moveresize_client->size_inc.height > 1)) popup_coords(moveresize_client, "%d x %d", lw, lh); }
void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) { ObCursor cur; gboolean mv = (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) || cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD)); gint up = 1; gint left = 1; if (moveresize_in_progress || !c->frame->visible || !(mv ? (c->functions & OB_CLIENT_FUNC_MOVE) : (c->functions & OB_CLIENT_FUNC_RESIZE))) return; if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) { cur = OB_CURSOR_NORTHWEST; up = left = -1; } else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) { cur = OB_CURSOR_NORTH; up = -1; } else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) { cur = OB_CURSOR_NORTHEAST; up = -1; } else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT)) cur = OB_CURSOR_EAST; else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)) cur = OB_CURSOR_SOUTHEAST; else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM)) cur = OB_CURSOR_SOUTH; else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) { cur = OB_CURSOR_SOUTHWEST; left = -1; } else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) { cur = OB_CURSOR_WEST; left = -1; } else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) cur = OB_CURSOR_SOUTHEAST; else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE)) cur = OB_CURSOR_MOVE; else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD)) cur = OB_CURSOR_MOVE; else g_assert_not_reached(); /* keep the pointer bounded to the screen for move/resize */ if (!grab_pointer(FALSE, TRUE, cur)) return; if (!grab_keyboard()) { ungrab_pointer(); return; } frame_end_iconify_animation(c->frame); moving = mv; moveresize_client = c; start_cx = c->area.x; start_cy = c->area.y; start_cw = c->area.width; start_ch = c->area.height; /* these adjustments for the size_inc make resizing a terminal more friendly. you essentially start the resize in the middle of the increment instead of at 0, so you have to move half an increment either way instead of a full increment one and 1 px the other. */ start_x = x - (mv ? 0 : left * c->size_inc.width / 2); start_y = y - (mv ? 0 : up * c->size_inc.height / 2); corner = cnr; button = b; key_resize_edge = -1; /* default to not putting max back on cancel */ was_max_horz = was_max_vert = FALSE; /* have to change start_cx and start_cy if going to do this.. if (corner == prop_atoms.net_wm_moveresize_move_keyboard || corner == prop_atoms.net_wm_moveresize_size_keyboard) XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0, c->area.width / 2, c->area.height / 2); */ cur_x = start_cx; cur_y = start_cy; cur_w = start_cw; cur_h = start_ch; moveresize_in_progress = TRUE; waiting_for_sync = 0; #ifdef SYNC if (config_resize_redraw && !moving && obt_display_extension_sync && moveresize_client->sync_request && moveresize_client->sync_counter && !moveresize_client->not_responding) { /* Initialize values for the resize syncing, and create an alarm for the client's xsync counter */ XSyncValue val; XSyncAlarmAttributes aa; /* set the counter to an initial value */ XSyncIntToValue(&val, 0); XSyncSetCounter(obt_display, moveresize_client->sync_counter, val); /* this will be incremented when we tell the client what we're looking for */ moveresize_client->sync_counter_value = 0; /* the next sequence we're waiting for with the alarm */ XSyncIntToValue(&val, 1); /* set an alarm on the counter */ aa.trigger.counter = moveresize_client->sync_counter; aa.trigger.wait_value = val; aa.trigger.value_type = XSyncAbsolute; aa.trigger.test_type = XSyncPositiveTransition; aa.events = True; XSyncIntToValue(&aa.delta, 1); moveresize_alarm = XSyncCreateAlarm(obt_display, XSyncCACounter | XSyncCAValue | XSyncCAValueType | XSyncCATestType | XSyncCADelta | XSyncCAEvents, &aa); } #endif }
int main (void) { { Display *display = XOpenDisplay(NULL); if (! display) { abort (); } int major = 3; int minor = 1; XSyncInitialize(display, &major, &minor); XSyncValue value; XSyncIntToValue(&value, 0); XSyncCounter counter = XSyncCreateCounter(display, value); static XSyncWaitCondition wait_list[1]; XSyncIntToValue(&value, 123); wait_list[0].trigger.counter = counter; wait_list[0].trigger.value_type = XSyncAbsolute; wait_list[0].trigger.wait_value = value; wait_list[0].trigger.test_type = XSyncPositiveTransition; printf ("XSyncAwait call\n"); XSyncAwait(display, wait_list, 1); printf ("XSyncAwait return\n"); printf ("XSync call\n"); XSync(display, 0); printf ("XSync return\n"); return 0; } { Display *display = XOpenDisplay (NULL); if (! display) { abort (); } int major = 3; int minor = 1; XSyncInitialize(display, &major, &minor); XSyncValue value; XSyncIntToValue(&value, 0); XSyncCounter counter = XSyncCreateCounter(display, value); static XSyncWaitCondition wait_list[1]; XSyncIntToValue(&value, 123); wait_list[0].trigger.counter = counter; wait_list[0].trigger.value_type = XSyncAbsolute; wait_list[0].trigger.wait_value = value; wait_list[0].trigger.test_type = XSyncPositiveTransition; printf ("XSyncAwait call\n"); XSyncAwait(display, wait_list, 1); printf ("XSyncAwait return\n"); printf ("XSync call\n"); XSync(display, 0); printf ("XSync return\n"); return 0; } }