2 * Copyright Neil Brown ©2021 <neil@brown.name>
3 * May be distributed under terms of GPLv2 - see file:COPYING
5 * X11 display driver for edlib, using xcb, cairopango, libxkbcommon etc.
7 * A different connection to the server will be created for each
8 * display. Maybe that can be optimised one day.
16 #include <xcb/xcbext.h>
21 #include <cairo-xcb.h>
24 #include <pango/pango.h>
25 #include <pango/pangocairo.h>
27 typedef struct PangoFontDescription {} PangoFontDescription;
28 typedef struct PangoLayout {} PangoLayout;
29 typedef struct PangoContext {} PangoContext;
30 typedef struct PangoFontMetrics {} PangoFontMetrics;
31 typedef struct PangoRectangle { int x,y,width,height;} PangoRectangle;
32 typedef enum { PANGO_STYLE_NORMAL, PANGO_STYLE_OBLIQUE, PANGO_STYLE_ITALIC
34 typedef enum { PANGO_VARIANT_NORMAL, PANGO_VARIANT_SMALL_CAPS } PangoVariant;
35 typedef enum { PANGO_WEIGHT_NORMAL, PANGO_WEIGHT_BOLD } PangoWeight;
36 PangoFontDescription *pango_font_description_new(void);
37 void pango_font_description_set_family_static(PangoFontDescription*, char*);
38 void pango_font_description_set_family(PangoFontDescription*, char*);
39 void pango_font_description_set_size(PangoFontDescription*, int);
40 void pango_font_description_set_style(PangoFontDescription*, PangoStyle);
41 void pango_font_description_set_variant(PangoFontDescription*, PangoVariant);
42 void pango_font_description_set_weight(PangoFontDescription*, PangoWeight);
43 #define PANGO_SCALE (1024)
45 PangoLayout *pango_cairo_create_layout(cairo_t*);
46 void g_object_unref(PangoLayout*);
47 PangoContext *pango_cairo_create_context(cairo_t *);
48 void pango_cairo_show_layout(cairo_t *, PangoLayout *);
49 PangoFontMetrics *pango_context_get_metrics(PangoContext*, PangoFontDescription*, void*);
50 void pango_font_description_free(PangoFontDescription*);
51 int pango_font_metrics_get_approximate_char_width(PangoFontMetrics *);
52 int pango_font_metrics_get_ascent(PangoFontMetrics *);
53 int pango_font_metrics_get_descent(PangoFontMetrics *);
54 void pango_font_metrics_unref(PangoFontMetrics *);
55 PangoContext* pango_layout_get_context(PangoLayout *);
56 int pango_layout_get_baseline(PangoLayout *);
57 void pango_layout_get_pixel_extents(PangoLayout *, PangoRectangle *, PangoRectangle *);
58 void pango_layout_set_font_description(PangoLayout *, PangoFontDescription *);
59 void pango_layout_set_text(PangoLayout*, const char *, int);
60 void pango_layout_xy_to_index(PangoLayout*, int, int, int*, int*);
64 //#include <xkbcommon/xkbcommon.h>
65 //#include <xkbcommon/xkbcommon-x11.h>
72 a_WM_STATE, a_STATE_ADD, a_STATE_REMOVE, a_STATE_FULLSCREEN,
75 static char *atom_names[NR_ATOMS] = {
76 [a_WM_STATE] = "_NET_WM_STATE",
77 [a_STATE_ADD] = "_NET_WM_STATE_ADD",
78 [a_STATE_REMOVE] = "_NET_WM_STATE_REMOVE",
79 [a_STATE_FULLSCREEN] = "_NET_WM_STATE_FULLSCREEN",
83 xcb_connection_t *conn safe;
86 const xcb_setup_t *setup safe;
87 const xcb_screen_t *screen safe;
88 xcb_atom_t atoms[NR_ATOMS];
92 xcb_visualtype_t *visual;
94 cairo_surface_t *surface safe;
95 PangoFontDescription *fd safe;
97 int charwidth, lineheight;
103 struct xkb_context *xkb;
104 int32_t xkb_device_id;
105 struct xkb_state *xkb_state;
108 /* FIXME use hash?? */
115 cairo_surface_t *surface safe;
119 static struct map *xcb_map;
120 DEF_LOOKUP_CMD(xcb_handle, xcb_map);
122 static cairo_t *get_pixmap(struct pane *home safe,
125 struct xcb_data *xd = home->data;
126 struct panes **pp, *ps;
127 cairo_surface_t *surface;
130 for (pp = &xd->panes; (ps = *pp) != NULL; pp = &(*pp)->next) {
133 if (ps->w == p->w && ps->h == p->h)
136 cairo_destroy(ps->ctx);
137 cairo_surface_destroy(ps->surface);
138 xcb_free_pixmap(xd->conn, ps->draw);
146 ps->draw = xcb_generate_id(xd->conn);
147 xcb_create_pixmap(xd->conn, xd->screen->root_depth, ps->draw,
148 xd->win, p->w, p->h);
149 surface = cairo_xcb_surface_create(
150 xd->conn, ps->draw, xd->visual, p->w, p->h);
153 ctx = cairo_create(surface);
157 ps->surface = surface;
159 pane_add_notify(home, p, "Notify:Close");
164 cairo_surface_destroy(surface);
166 xcb_free_pixmap(xd->conn, ps->draw);
171 static struct panes *find_pixmap(struct xcb_data *xd safe, struct pane *p safe,
172 int *xp safe, int *yp safe)
175 struct panes *ret = NULL;
177 while (!ret && p->parent != p) {
179 for (ps = xd->panes; ps ; ps = ps->next)
199 static inline double cvt(int i)
201 return (float)i / 1000.0;
204 static void parse_attrs(
205 struct pane *home safe, const char *cattrs, int scale,
206 struct rgb *fgp, struct rgb *bgp, bool *underline,
207 PangoFontDescription **fdp)
209 char *attrs = strdup(cattrs ?: "");
212 char *fg = NULL, *bg = NULL;
216 PangoFontDescription *fd = NULL;
217 PangoStyle style = PANGO_STYLE_NORMAL;
218 PangoVariant variant = PANGO_VARIANT_NORMAL;
219 PangoWeight weight = PANGO_WEIGHT_NORMAL;
222 fd = pango_font_description_new();
224 pango_font_description_set_family_static(fd, "mono");
227 while ((word = strsep(&ap, ",")) != NULL) {
228 if (fd && strncmp(word, "family:", 7) == 0)
229 pango_font_description_set_family(fd, word+7);
230 if (strcmp(word, "large") == 0)
232 if (strcmp(word, "small") == 0)
234 if (isdigit(word[0])) {
236 double s = strtod(word, &end);
237 if (end && end != word && !*end)
238 size = trunc(s * 1000.0);
242 if (strcmp(word, "oblique") == 0)
243 style = PANGO_STYLE_OBLIQUE;
244 if (strcmp(word, "italic") == 0)
245 style = PANGO_STYLE_ITALIC;
246 if (strcmp(word, "normal") == 0)
247 style = PANGO_STYLE_NORMAL;
248 if (strcmp(word, "small-caps") == 0)
249 variant = PANGO_VARIANT_SMALL_CAPS;
251 if (strcmp(word, "bold") == 0)
252 weight = PANGO_WEIGHT_BOLD;
253 if (strcmp(word, "nobold") == 0)
254 weight = PANGO_WEIGHT_NORMAL;
256 if (strncmp(word, "fg:", 3) == 0)
258 if (strncmp(word, "bg:", 3) == 0)
260 if (strcmp(word, "inverse") == 0)
262 if (strcmp(word, "underline") == 0)
278 struct call_return ret = call_ret(all, "colour:map", home,
281 fgp->g = cvt(ret.i2);
286 struct call_return ret = call_ret(all, "colour:map", home,
289 bgp->g = cvt(ret.i2);
294 pango_font_description_set_size(fd, size * scale / PANGO_SCALE);
295 if (style != PANGO_STYLE_NORMAL)
296 pango_font_description_set_style(fd, style);
297 if (variant != PANGO_VARIANT_NORMAL)
298 pango_font_description_set_variant(fd, variant);
299 if (weight != PANGO_WEIGHT_NORMAL)
300 pango_font_description_set_weight(fd, weight);
309 struct call_return *cr = container_of(ci->comm, struct call_return, c);
315 DEF_CMD(xcb_close_display)
317 /* If this is only display, then refuse to close this one */
318 struct call_return cr;
319 struct xcb_data *xd = ci->home->data;
321 call("Message", ci->focus, 0, NULL, xd->noclose);
326 call_comm("editor:notify:all-displays", ci->focus, &cr.c);
328 pane_close(ci->home);
330 call("Message", ci->focus, 0, NULL,
331 "Cannot close only window.");
335 DEF_CMD(xcb_set_noclose)
337 struct xcb_data *xd = ci->home->data;
342 xd->noclose = strdup(ci->str);
346 DEF_CMD(xcb_external_viewer)
348 //struct xcb_data *xd = ci->home->data;
353 DEF_CMD(xcb_fullscreen)
355 struct xcb_data *xd = ci->home->data;
356 xcb_client_message_event_t msg = {};
358 msg.response_type = XCB_CLIENT_MESSAGE;
360 msg.window = xd->win;
361 msg.type = xd->atoms[a_WM_STATE];
363 msg.data.data32[0] = xd->atoms[a_STATE_ADD];
365 msg.data.data32[0] = xd->atoms[a_STATE_REMOVE];
366 msg.data.data32[1] = xd->atoms[a_STATE_FULLSCREEN];
367 msg.data.data32[2] = 0;
368 msg.data.data32[3] = 1; /* source indicator */
370 xcb_send_event(xd->conn, 0, xd->screen->root,
371 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
372 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
373 (void*)msg.data.data8);
380 struct xcb_data *xd = ci->home->data;
381 xcb_destroy_window(xd->conn, xd->win);
382 xcb_disconnect(xd->conn);
389 struct xcb_data *xd = ci->home->data;
390 const char *attr = ci->str;
391 struct panes *src = NULL;
397 parse_attrs(ci->home, attr, PANGO_SCALE, NULL, &bg, NULL, NULL);
399 src = find_pixmap(xd, ci->focus->parent, &x, &y);
400 bg.r = bg.g = bg.b = 1.0;
403 pm = get_pixmap(ci->home, ci->focus);
407 cairo_set_source_surface(pm, src->surface, -x - ci->focus->x,
411 cairo_set_source_rgb(pm, bg.r, bg.g, bg.b);
412 cairo_rectangle(pm, 0.0, 0.0,
413 (double)ci->focus->w, (double)ci->focus->h);
416 pane_damaged(ci->home, DAMAGED_POSTORDER);
420 DEF_CMD(xcb_text_size)
422 struct xcb_data *xd = ci->home->data;
423 const char *attr = ci->str2 ?: "";
424 const char *str = ci->str ?: "";
425 int scale = ci->num2;
427 PangoFontDescription *fd;
434 parse_attrs(ci->home, attr, scale, NULL, NULL, NULL, &fd);
435 /* If we use an empty string, line-height it wrong */
436 layout = pango_cairo_create_layout(xd->cairo);
437 pango_layout_set_text(layout, *str ? str : "M", -1);
438 pango_layout_set_font_description(layout, fd);
439 pango_layout_get_pixel_extents(layout, NULL, &log);
440 baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
444 else if (log.width <= ci->num)
445 max_bytes = strlen(str);
447 pango_layout_xy_to_index(layout, 1000*ci->num,
448 baseline, &max_bytes, NULL);
450 comm_call(ci->comm2, "cb", ci->focus, max_bytes, NULL, NULL,
451 baseline, NULL, NULL,
452 str && *str ? log.width : 0,
455 pango_font_description_free(fd);
456 g_object_unref(layout);
460 DEF_CMD(xcb_draw_text)
462 struct xcb_data *xd = ci->home->data;
463 const char *str = ci->str;
464 const char *attr = ci->str2;
469 PangoFontDescription *fd;
479 ps = find_pixmap(xd, ci->focus, &xo, &yo);
484 pane_damaged(ci->home, DAMAGED_POSTORDER);
487 scale = ci->num2 * 10 / xd->charwidth;
489 parse_attrs(ci->home, attr, scale, &fg, &bg, &ul, &fd);
493 layout = pango_cairo_create_layout(ctx);
494 pango_layout_set_text(layout, str, -1);
495 pango_layout_set_font_description(layout, fd);
496 pango_layout_get_pixel_extents(layout, NULL, &log);
497 baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
499 cairo_set_source_rgb(ctx, bg.r, bg.g, bg.b);
500 cairo_rectangle(ctx, x+log.x, y - baseline + log.y,
501 log.width, log.height);
504 cairo_set_source_rgb(ctx, fg.r, fg.g, fg.b);
506 /* Draw an underline */
507 cairo_rectangle(ctx, x+log.x, y+2+log.y,
512 cairo_move_to(ctx, x, y - baseline);
513 pango_cairo_show_layout(ctx, layout);
517 /* draw a cursor - outline box if not in-focus,
518 * inverse-video if it is.
521 pango_font_description_free(fd);
522 g_object_unref(layout);
526 DEF_CMD(xcb_draw_image)
528 //struct xcb_data *xd = ci->home->data;
533 static struct panes *sort_split(struct panes *p)
535 /* consider 'p' to be a list of panes with
536 * ordered subsets (ordered by p->abs_z).
537 * Remove every other such subset and return them
539 * If p is ordered, this means we return NULL.
541 struct panes *ret, **end = &ret;
544 for (; p && p->next; p = next) {
545 /* If these are not ordered, attach p->next at
546 * 'end', and make 'end' point to &p->next.
549 if (p->p->abs_z <= next->p->abs_z)
558 static struct panes *sort_merge(struct panes *p1, struct panes *p2)
560 /* merge p1 and p2 and return result */
561 struct panes *ret, **end = &ret;
565 /* if both arg large or smaller than lastz, choose
566 * least, else choose largest
568 struct panes *lo, *hi, *choice;
569 if (p1->p->abs_z <= p2->p->abs_z) {
574 if (lo->p->abs_z >= lastz || hi->p->abs_z <= lastz)
592 DEF_CMD(xcb_refresh_post)
594 struct xcb_data *xd = ci->home->data;
597 time_start(TIME_WINDOW);
598 /* First: ensure panes are sorted */
599 while ((ps = sort_split(xd->panes)) != NULL)
600 xd->panes = sort_merge(xd->panes, ps);
602 /* Now copy all panes onto the window */
603 for (ps = xd->panes; ps; ps = ps->next) {
604 double lox, hix, loy, hiy;
605 struct xy rel, lo, hi;
607 rel = pane_mapxy(ps->p, ci->home, 0, 0, False);
608 lo = pane_mapxy(ps->p, ci->home, 0, 0, True);
609 hi = pane_mapxy(ps->p, ci->home, ps->p->w, ps->p->h, True);
610 lox = lo.x; loy = lo.y;
611 hix = hi.x; hiy = hi.y;
612 cairo_save(xd->cairo);
613 cairo_set_source_surface(xd->cairo, ps->surface,
615 cairo_rectangle(xd->cairo, lox, loy, hix, hiy);
616 cairo_fill(xd->cairo);
617 cairo_restore(xd->cairo);
619 time_stop(TIME_WINDOW);
624 DEF_CMD(xcb_pane_close)
626 struct xcb_data *xd = ci->home->data;
627 struct panes **pp, *ps;
629 for (pp = &xd->panes; (ps = *pp) != NULL; pp = &(*pp)->next) {
630 if (ps->p != ci->focus)
634 cairo_destroy(ps->ctx);
635 cairo_surface_destroy(ps->surface);
636 xcb_free_pixmap(xd->conn, ps->draw);
638 pane_damaged(ci->home, DAMAGED_POSTORDER);
644 DEF_CMD(xcb_notify_display)
646 struct xcb_data *xd = ci->home->data;
647 comm_call(ci->comm2, "callback:display", ci->home, xd->last_event);
651 static void handle_button(struct pane *home safe,
652 xcb_button_press_event_t *be safe)
654 struct xcb_data *xd = home->data;
655 bool press = (be->response_type & 0x7f) == XCB_BUTTON_PRESS;
657 char key[2+2+2+9+1+1];
661 xd->motion_blocked = False;
662 if (be->state & XCB_KEY_BUT_MASK_MOD_1)
664 if (be->state & XCB_KEY_BUT_MASK_CONTROL)
666 if (be->state & XCB_KEY_BUT_MASK_SHIFT)
669 strcat(key, ":Press-X");
671 strcpy(key, ":Release-X");
672 key[strlen(key) - 1] = '0' + be->detail;
673 xd->last_event = time(NULL);
674 call("Mouse-event", home, be->detail, NULL, key,
675 press?1:2, NULL, mod,
676 be->event_x, be->event_y);
679 static void handle_motion(struct pane *home safe,
680 xcb_motion_notify_event_t *mne safe)
682 struct xcb_data *xd = home->data;
683 xcb_query_pointer_cookie_t c;
684 xcb_query_pointer_reply_t *qpr;
686 int x = mne->event_x, y = mne->event_y;
688 if (xd->motion_blocked)
690 ret = call("Mouse-event", home, 0, NULL, ":Motion",
691 3, NULL, NULL, x, y);
693 xd->motion_blocked = True;
694 c = xcb_query_pointer(xd->conn, xd->win);
695 qpr = xcb_query_pointer_reply(xd->conn, c, NULL);
699 static void handle_focus(struct pane *home safe, xcb_focus_in_event_t *fie safe)
701 struct xcb_data *xd = home->data;
702 bool in = (fie->response_type & 0x7f) == XCB_FOCUS_IN;
708 pt = call_ret(mark, "doc:point", p);
710 call("view:changed", p, 0, pt);
712 call("pane:refocus", home);
715 static void handle_key(struct pane *home safe, xcb_key_press_event_t *kpe safe)
717 //struct xcb_data *xd = home->data;
719 xcb_key_press_event_t *kpe;
722 xkb_state_update_key(xd->xkb_state, kpe->keycode,
724 keysym = xkb_state_key_get_one_sym(xd->xkb_state,
726 xkb_keysym_get_name(keysym, name, sizeof(name));
727 xkb_state_key_get_utf8(xd->xkb_state, kpe->keycode,
730 if (kpe->detail == 24)
731 call("event:deactivate", home);
735 //XLookupString(&xke, &buf, sizeof(buf), &keysym, NULL);
738 static void handle_configure(struct pane *home safe,
739 xcb_configure_notify_event_t *cne safe)
741 struct xcb_data *xd = home->data;
743 pane_resize(home, 0, 0, cne->width, cne->height);
744 cairo_xcb_surface_set_size(xd->surface, cne->width, cne->height);
749 struct xcb_data *xd = ci->home->data;
750 xcb_generic_event_t *ev;
752 while ((ev = xcb_poll_for_event(xd->conn)) != NULL) {
753 switch (ev->response_type & 0x7f) {
755 case XCB_KEY_RELEASE:
756 time_start(TIME_KEY);
757 handle_key(ci->home, safe_cast (void*)ev);
760 case XCB_BUTTON_PRESS:
761 case XCB_BUTTON_RELEASE:
762 time_start(TIME_KEY);
763 handle_button(ci->home, (void*)ev);
766 case XCB_MOTION_NOTIFY:
767 time_start(TIME_KEY);
768 handle_motion(ci->home, (void*)ev);
773 time_start(TIME_WINDOW);
774 handle_focus(ci->home, (void*)ev);
775 time_stop(TIME_WINDOW);
778 pane_damaged(ci->home, DAMAGED_POSTORDER);
780 case XCB_CONFIGURE_NOTIFY:
781 time_start(TIME_WINDOW);
782 handle_configure(ci->home, (void*)ev);
783 time_stop(TIME_WINDOW);
786 LOG("ignored %x", ev->response_type);
793 static struct pane *xcb_display_init(const char *d safe, struct pane *focus safe)
797 xcb_connection_t *conn;
798 xcb_intern_atom_cookie_t cookies[NR_ATOMS];
799 xcb_screen_iterator_t iter;
800 xcb_depth_iterator_t di;
808 cairo_surface_t *surface;
809 PangoFontDescription *fd;
810 // FIXME SCALE from environ?? or pango_cairo_context_set_resolution dpi
811 // 254 * width_in_pixels / width_in_millimeters / 10
813 conn = xcb_connect(d, &screen);
819 xd->motion_blocked = True;
823 xd->display = strdup(d);
824 xd->setup = safe_cast xcb_get_setup(conn);
825 iter = xcb_setup_roots_iterator(xd->setup);
826 for (i = 0; i < screen; i++)
827 xcb_screen_next(&iter);
828 xd->screen = safe_cast iter.data;
830 di = xcb_screen_allowed_depths_iterator(xd->screen);
831 while (di.data && di.data->depth < 24)
833 //?? look for class = TrueColor??
834 xd->visual = xcb_depth_visuals(di.data);
836 for (i = 0; i < NR_ATOMS; i++) {
837 char *n = atom_names[i];
840 cookies[i] = xcb_intern_atom(conn, 0, strlen(n), n);
843 xd->win = xcb_generate_id(conn);
844 valwin[0] = xd->screen->white_pixel;
845 valwin[1] = (XCB_EVENT_MASK_KEY_PRESS |
846 XCB_EVENT_MASK_KEY_RELEASE |
847 XCB_EVENT_MASK_BUTTON_PRESS |
848 XCB_EVENT_MASK_BUTTON_RELEASE |
849 // XCB_EVENT_MASK_ENTER_WINDOW |
850 // XCB_EVENT_MASK_LEAVE_WINDOW |
851 XCB_EVENT_MASK_STRUCTURE_NOTIFY |
852 XCB_EVENT_MASK_EXPOSURE |
853 XCB_EVENT_MASK_POINTER_MOTION |
854 // FIXME XCB_EVENT_MASK_POINTER_MOTION_HINT |
857 xcb_create_window(conn, XCB_COPY_FROM_PARENT, xd->win,
861 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
862 xd->screen->root_visual,
863 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
867 surface = cairo_xcb_surface_create(
868 conn, xd->win, xd->visual, 100, 100);
871 xd->surface = surface;
872 cairo = cairo_create(xd->surface);
876 fd = pango_font_description_new();
880 pango_font_description_set_family(xd->fd, "mono");
881 pango_font_description_set_size(xd->fd, 12 * PANGO_SCALE);
883 layout = pango_cairo_create_layout(xd->cairo);
884 pango_layout_set_font_description(layout, fd);
885 pango_layout_set_text(layout, "M", 1);
886 pango_layout_get_pixel_extents(layout, NULL, &log);
887 g_object_unref(layout);
888 xd->lineheight = log.height;
889 xd->charwidth = log.width;
891 valwin[0] = xd->charwidth * 80;
892 valwin[1] = xd->lineheight * 26;
893 xcb_configure_window(conn, xd->win,
894 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
896 cairo_xcb_surface_set_size(xd->surface, valwin[0], valwin[1]);
898 /* Now resolve all those cookies */
899 for (i = 0; i < NR_ATOMS; i++) {
900 xcb_intern_atom_reply_t *r;
901 r = xcb_intern_atom_reply(conn, cookies[i], NULL);
904 xd->atoms[i] = r->atom;
909 xd->xkb = safe_cast xkb_context_new(XCB_CONTEXT_NO_FLAGS);
910 xd->xkb_device_id = xkb_x11_get_core_keyboard_device_id(conn);
911 xd->xkb_state = xkb_x11_state_new_from_device(xd->xkb_keymap, conn,
916 * WM_PROTOCOLS WM_DELETE_WINDOW WM_TAKE_FOCUS _NET_WM_PING _NET_WM_SYN_REQUEST??
917 * WM_NORMAL_HINTS WM_HINTS
920 xcb_map_window(conn, xd->win);
922 p = pane_register(pane_root(focus), 1, &xcb_handle.c, xd);
925 pane_resize(p, 0, 0, xd->charwidth*80, xd->lineheight*26);
926 call_comm("event:read", p, &xcb_input, xcb_get_file_descriptor(conn));
927 attr_set_str(&p->attrs, "DISPLAY", d);
928 snprintf(scale, sizeof(scale), "%dx%d", xd->charwidth, xd->lineheight);
929 attr_set_str(&p->attrs, "scale:M", scale);
930 //attr_set_int(&p->attrs, "scale", 2000);
933 cairo_destroy(xd->cairo);
934 cairo_surface_destroy(xd->surface);
935 xcb_disconnect(conn);
944 const char *d = ci->str;
948 p = xcb_display_init(d, ci->focus);
950 return comm_call(ci->comm2, "cb", p);
954 DEF_CMD(xcb_new_display)
957 char *d = pane_attr_get(ci->focus, "DISPLAY");
961 p = xcb_display_init(d, ci->focus);
963 p = call_ret(pane, "editor:activate-display", p);
965 home_call(ci->focus, "doc:attach-view", p, 1);
969 void edlib_init(struct pane *ed safe)
971 call_comm("global-set-command", ed, &display_xcb, 0, NULL,
972 "attach-display-x11");
973 call_comm("global-set-command", ed, &xcb_new_display, 0, NULL,
974 "interactive-cmd-x11window");
976 xcb_map = key_alloc();
978 key_add(xcb_map, "Display:close", &xcb_close_display);
979 key_add(xcb_map, "Display:set-noclose", &xcb_set_noclose);
980 key_add(xcb_map, "Display:external-viewer", &xcb_external_viewer);
981 key_add(xcb_map, "Display:fullscreen", &xcb_fullscreen);
982 key_add(xcb_map, "Display:new", &xcb_new_display);
984 key_add(xcb_map, "Close", &xcb_close);
985 key_add(xcb_map, "Free", &edlib_do_free);
986 key_add(xcb_map, "Draw:clear", &xcb_clear);
987 key_add(xcb_map, "Draw:text-size", &xcb_text_size);
988 key_add(xcb_map, "Draw:text", &xcb_draw_text);
989 key_add(xcb_map, "Draw:image", &xcb_draw_image);
990 key_add(xcb_map, "Refresh:postorder", &xcb_refresh_post);
991 key_add(xcb_map, "all-displays", &xcb_notify_display);
992 key_add(xcb_map, "Notify:Close", &xcb_pane_close);