Loading ...
Sorry, an error occurred while loading the content.

HIView + compositing mode

Expand Messages
  • Jjgod Jiang
    Hi all, On moving gvim towards modern Carbon APIs, we hope to replace current QuickDraw stuff with Quartz, and instead of drawing directly to the window port,
    Message 1 of 1 , Apr 8, 2007
    • 0 Attachment
      Hi all,

      On moving gvim towards modern Carbon APIs, we hope to replace
      current QuickDraw stuff with Quartz, and instead of drawing
      directly to the window port, we obtain a content HIView first.

      But according to HIView Programming Guide [1],

      The HIView drawing model does not support drawing to the
      screen outside of a kEventControlDraw handler. If you
      want to redraw a view, you should mark areas as being
      invalid (using the HIViewSetNeedsDisplay,
      HIViewSetNeedsDisplayInRegion or, in Mac OS X v10.4 and
      later, HIViewSetNeedsDisplayInRect and
      HIViewSetNeedsDisplayInShape functions) and draw only
      when the system tells you to do so. This delayed drawing
      model is required to support correct compositing of
      overlapping views.

      We all know a lot of incoming calls in gui_mch_* are not
      following this model (but they fits in QuickDraw model quite
      well), for example, gui_mch_draw_string() will request to
      have a line of string drawing immediately, gui_mch_clear_all()
      will request to clear the window content immediately,
      gui_mch_delete_lines() will request to move some lines up
      immediately... How to make them fit the current "delayed
      drawing model"?

      My current approach is create a drawing_request queue:

      enum drawing_request_type {
      REQ_CLEAR_ALL,
      REQ_CLEAR_BLOCK,
      REQ_INVERT_RECT,
      REQ_FLASH,
      REQ_DRAW_STRING,
      REQ_DELETE_LINES,
      REQ_INSERT_LINES
      };

      typedef struct drawing_request {
      enum drawing_request_type type;

      union {
      /* REQ_DRAW_STRING */
      struct {
      int row;
      int col;
      char_u *s;
      int len;
      int flag;
      } str;

      /* REQ_CLEAR_BLOCK, REQ_INVERT_RECT */
      CGRect rect;
      } u;

      struct drawing_request *next;
      } drawing_request;

      and new incoming drawing request will be append to the
      queue, then call HIViewSetNeedsDisplay(),

      void gui_mch_draw_string(int row, int col, char_u *s,
      int len, int flags)
      {
      request_draw_string(row, col, s, len, flags);
      }

      drawing_request *request_draw_string(int row, int col,
      char_u *s, int len,
      int flag)
      {
      drawing_request *req;

      req = (drawing_request *)
      malloc(sizeof(drawing_request));

      req->type = REQ_DRAW_STRING;
      req->u.str.row = row;
      req->u.str.col = row;
      // Is simply save the pointer ok? will vim change
      // it's content after the gui_mch_draw_string call?
      req->u.str.s = s;
      req->u.str.len = len;
      req->u.str.flag = flag;

      req->next = NULL;

      request_append(req);
      HIViewSetNeedsDisplay(gui.mainView, true);

      return req;
      }

      When handling kEventControlDraw event for the content HIView,
      we can:

      for (req = req_queue_head; req != NULL; req = req->next)
      {
      switch (req->type)
      {
      case REQ_DRAW_STRING:
      ... (do real drawing stuff)
      break;

      case REQ_CLEAR_ALL:
      ...
      break;

      ...
      }
      }

      // clean up the queue after all processing is finished
      request_clean_up();

      What do you think of this approach?

      - jjgod
    Your message has been successfully submitted and would be delivered to recipients shortly.