[X2Go-Commits] [nx-libs] 04/18: nx-X11/programs/Xserver/hw/nxagent/Screen.c: implement split algorithm/functions.

git-admin at x2go.org git-admin at x2go.org
Fri Jul 13 07:30:52 CEST 2018


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch 3.6.x-rpm-debug
in repository nx-libs.

commit aaf78fdff9a4aa9d2b32bc8590976a4befcb02d7
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Mon Mar 19 00:38:59 2018 +0100

    nx-X11/programs/Xserver/hw/nxagent/Screen.c: implement split algorithm/functions.
---
 nx-X11/programs/Xserver/hw/nxagent/Screen.c | 215 ++++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)

diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
index cd82111..1f2b08f 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/Screen.c
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
@@ -3910,6 +3910,221 @@ int nxagentChangeScreenConfig(int screen, int width, int height)
 }
 
 /*
+ * Structure containing a list of splits.
+ *
+ * Only used locally, not exported.
+ */
+typedef struct {
+  size_t  x_count;
+  size_t  y_count;
+  INT32  *x_splits;
+  INT32  *y_splits;
+} nxagentScreenSplits;
+
+/*
+ * Helper function that takes a potential split point, the window bounds,
+ * a split count and a splits array.
+ *
+ * The function checks if the split point is within bounds, not already
+ * contained in the list and adds a new split point, modifying both the
+ * count parameter and the splits list.
+ *
+ * In case of errors, does nothing.
+ */
+static void nxagentAddToSplits(const CARD16 test_edge, const CARD16 rwin_start, const CARD16 rwin_end, size_t *split_count, INT32 *splits) {
+  if ((!(split_count)) || (!(splits))) {
+    return;
+  }
+
+  /* FIXME: think through and check edge case: 1px split. */
+  if ((rwin_start < test_edge) && (rwin_end > test_edge)) {
+    /* Edge somewhere inside of agent window, split point. */
+
+    /* Filter out if split point exists already. */
+    Bool exists = FALSE;
+    for (size_t i = 0; i < (*split_count); ++i) {
+      if (splits[i] == test_edge) {
+        exists = TRUE;
+        break;
+      }
+    }
+
+    if (!(exists)) {
+      splits[(*split_count)++] = test_edge;
+    }
+  }
+}
+
+/* Helper function used while sorting the split lists. */
+static int nxagentCompareSplits(const void *lhs, const void *rhs) {
+  int ret = 0;
+
+  const INT32 lhs_ = *((INT32*)(lhs)),
+              rhs_ = *((INT32*)(rhs));
+
+  if (lhs_ < rhs_) {
+    ret = -1;
+  }
+  else if (lhs_ > rhs_) {
+    ret = 1;
+  }
+
+  return(ret);
+}
+
+/* Helper function that deallocates a split list. */
+static void nxagentFreeSplits(nxagentScreenSplits **splits) {
+  if ((!(splits)) || (!(*splits))) {
+    return;
+  }
+
+  nxagentScreenSplits *splits_ = (*splits);
+
+  splits_->x_count = 0;
+  splits_->y_count = 0;
+
+  SAFE_FREE(splits_->x_splits);
+  SAFE_FREE(splits_->y_splits);
+  SAFE_FREE(splits_);
+}
+
+/*
+ * Helper function compacting an nxagentScreenSplits structure.
+ * The initial allocation assumes the worst case and overallocates memory,
+ * upper bounded by the maximum count of possible splits for a given screen
+ * configuration.
+ * This function compacts the lists back down into what is necessary only.
+ *
+ * In case of memory allocation errors, it frees all allocated datan and sets
+ * the splits list pointer to NULL!
+ */
+static void nxagentCompactSplits(nxagentScreenSplits **splits, const size_t actual_x_count, const size_t actual_y_count) {
+  if ((!(splits)) || (!(*splits))) {
+    return;
+  }
+
+  nxagentScreenSplits *splits_ = (*splits);
+
+  splits_->x_count = actual_x_count;
+  INT32 *new_data = NULL;
+  if (actual_x_count) {
+    /* Compact to accomodate actual data. */
+    new_data = realloc(splits_->x_splits, sizeof(INT32) * actual_x_count);
+
+    if (!(new_data)) {
+      nxagentFreeSplits(splits);
+
+      return;
+    }
+
+    splits_->x_splits = new_data;
+  }
+  else {
+    /* No splits in this dimension, drop data. */
+    SAFE_FREE(splits_->x_splits);
+  }
+
+  splits_->y_count = actual_y_count;
+  if (actual_y_count) {
+    new_data = realloc(splits_->y_splits, sizeof(INT32) * actual_y_count);
+
+    if (!(new_data)) {
+      nxagentFreeSplits(splits);
+
+      return;
+    }
+
+    splits_->y_splits = new_data;
+  }
+  else {
+    /* No splits in this dimension, drop data. */
+    SAFE_FREE(splits_->y_splits);
+  }
+}
+
+/*
+ * Generate a list of splits.
+ * This is based upon the client's system configuration and will
+ * generally create more splits than we need/want.
+ *
+ * In case of errors, returns NULL.
+ */
+static nxagentScreenSplits* nxagentGenerateScreenSplitList(const XineramaScreenInfo *screen_info, const size_t screen_count) {
+  nxagentScreenSplits *ret = NULL;
+
+  if (!(screen_info)) {
+    return(ret);
+  }
+
+  /*
+   * The maximum number of split points per axis
+   * is screen_count * 2 due to the rectangular nature of a screen
+   * (and hence two vertical or horizontal edges).
+   */
+  size_t split_counts = (screen_count * 2);
+
+  ret = calloc(1, sizeof(nxagentScreenSplits));
+  if (!ret) {
+    return(ret);
+  }
+
+  ret->x_splits = calloc(split_counts, sizeof(INT32));
+  ret->y_splits = calloc(split_counts, sizeof(INT32));
+  if ((!(ret->x_splits)) || (!(ret->y_splits))) {
+    SAFE_FREE(ret->x_splits);
+    SAFE_FREE(ret);
+
+    return(ret);
+  }
+
+  /*
+   * Initialize split arrays to -1, denoting no split.
+   * Could be done only for the first invalid element, but play it safe.
+   */
+  for (size_t i = 0; i < split_counts; ++i) {
+    ret->x_splits[i] = ret->y_splits[i] = -1;
+  }
+
+  const CARD16 sess_x_start = nxagentOption(X),
+               sess_y_start = nxagentOption(Y),
+               sess_x_end   = (sess_x_start + nxagentOption(Width)),
+               sess_y_end   = (sess_y_start + nxagentOption(Height));
+
+  size_t actual_x_splits = 0,
+         actual_y_splits = 0;
+
+  for (size_t i = 0; i < screen_count; ++i) {
+    /* Handle x component. */
+    size_t start_x = screen_info[i].x_org,
+           end_x = start_x + screen_info[i].width;
+
+    /* Left edge. */
+    nxagentAddToSplits(start_x, sess_x_start, sess_x_end, &actual_x_splits, ret->x_splits);
+
+    /* Right edge. */
+    nxagentAddToSplits(end_x, sess_x_start, sess_x_end, &actual_x_splits, ret->x_splits);
+
+    /* Handle y component. */
+    size_t start_y = screen_info[i].y_org,
+           end_y = start_y + screen_info[i].height;
+
+    /* Top edge. */
+    nxagentAddToSplits(start_y, sess_y_start, sess_y_end, &actual_y_splits, ret->y_splits);
+
+    /* Bottom edge. */
+    nxagentAddToSplits(end_y, sess_y_start, sess_y_end, &actual_y_splits, ret->y_splits);
+  }
+
+  /*
+   * Fetched all split points.
+   * Compact data and handle errors.
+   */
+  nxagentCompactSplits(&ret, actual_x_splits, actual_y_splits);
+
+  return(ret);
+}
+
+/*
  Destroy an output after removing it from any crtc that might reference it
  */
 void nxagentDropOutput(RROutputPtr o) {

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/nx-libs.git


More information about the x2go-commits mailing list