/** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, EGLNativeWindowType native_window, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_screen_iterator_t s; xcb_generic_error_t *error; xcb_drawable_t window = (uintptr_t )native_window; (void) drv; dri2_surf = malloc(sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) goto cleanup_surf; dri2_surf->region = XCB_NONE; if (type == EGL_PBUFFER_BIT) { dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, dri2_surf->drawable, s.data->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { dri2_surf->drawable = window; } if (dri2_dpy->dri2) { dri2_surf->dri_drawable = (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, type == EGL_WINDOW_BIT ? dri2_conf->dri_double_config : dri2_conf->dri_single_config, dri2_surf); } else { assert(dri2_dpy->swrast); dri2_surf->dri_drawable = (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen, dri2_conf->dri_double_config, dri2_surf); } if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } if (dri2_dpy->dri2) { xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); } else { swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE)); } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); if (reply == NULL || error != NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); free(error); goto cleanup_dri_drawable; } dri2_surf->base.Width = reply->width; dri2_surf->base.Height = reply->height; free(reply); } /* we always copy the back buffer to front */ dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; return &dri2_surf->base; cleanup_dri_drawable: dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); cleanup_pixmap: if (type == EGL_PBUFFER_BIT) xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); cleanup_surf: free(dri2_surf); return NULL; }
/* Prepare the stack of "exposed windows" and init the placing animation frames. */ static void _show() { uint8_t i; int rows, cols; int row_i, col_i; int row_cols; xcb_rectangle_t generic_cell, root_r; xcb_params_cw_t p; uint32_t m; _exposed_win_t *tmp_ew, *last_exp_win; fwm_mwin_t *tmp_man_win; _exposed_win_t **ordered_exp_wins; /* Get effects window and create buffer + picture. */ if ((_this.win = fwm_composite_get_effects_window()) == XCB_NONE) { return; /* The effects window is busy! */ } XCB_AUX_ADD_PARAM(&m, &p, event_mask, XCB_EVENT_MASK_BUTTON_PRESS); xcb_aux_change_window_attributes(gd.conn, _this.win, m, &p); _this.win_buffer = xcb_generate_id(gd.conn); xcb_create_pixmap(gd.conn, gd.def_screen->root_depth, _this.win_buffer, _this.win, gd.def_screen->width_in_pixels, gd.def_screen->height_in_pixels); _this.win_buffer_pic = fwm_render_create_picture(_this.win_buffer, XCB_NONE, NULL); root_r.x = root_r.y = 0; root_r.width = gd.def_screen->width_in_pixels; root_r.height = gd.def_screen->height_in_pixels; _clean_rect(&root_r); /* Decide how to place window thumbs. */ _find_cells(gd.def_screen->height_in_pixels, gd.def_screen->width_in_pixels, gd.win_count, &rows, &cols); generic_cell.width = (gd.def_screen->width_in_pixels / cols) - 20; generic_cell.height = (gd.def_screen->height_in_pixels / rows) - 20; /* Start preparing exposed windows. */ ordered_exp_wins = malloc(sizeof (_exposed_win_t *) * gd.win_count); tmp_man_win = gd.ws->top->next; last_exp_win = malloc(sizeof (_exposed_win_t)); last_exp_win->managed_win = tmp_man_win; last_exp_win->prev = NULL; _this.bottom = last_exp_win; ordered_exp_wins[0] = last_exp_win; tmp_man_win = tmp_man_win->next; i = 1; while (tmp_man_win != gd.ws->top->next) { tmp_ew = malloc(sizeof (_exposed_win_t)); tmp_ew->managed_win = tmp_man_win; tmp_ew->prev = last_exp_win; tmp_ew->next = NULL; last_exp_win->next = tmp_ew; last_exp_win = tmp_ew; ordered_exp_wins[i++] = tmp_ew; tmp_man_win = tmp_man_win->next; } _this.top = last_exp_win; qsort(ordered_exp_wins, gd.win_count, sizeof (_exposed_win_t *), _is_higher_than); col_i = row_i = 0; generic_cell.x = 0; for (row_i = 0; row_i < rows; row_i++) { /* Treats last line in a different way to center if it was not full. */ if (row_i == rows - 1) { row_cols = gd.win_count - row_i * cols; if (row_cols < cols) { generic_cell.x = ((cols - row_cols) * generic_cell.width + 60) / 2; } } else { row_cols = cols; } qsort(&ordered_exp_wins[row_i * cols], row_cols, sizeof (_exposed_win_t *), _is_more_left_placed_than); for (col_i = 0; col_i < row_cols; col_i++) { _setup_exposed_win(ordered_exp_wins[row_i * cols + col_i], generic_cell, col_i, row_i); } } free(ordered_exp_wins); xcb_flush(gd.conn); _this.state = _PLACING; _this.remaining_steps = _TRANS_FRAMES; for (i = 1; i < _TRANS_FRAMES; i++) { fwm_animan_append_action(_paint_place_step, NULL, i); } fwm_animan_append_action(_paint_final_place_step, NULL, i + 1); }
int main(int arg, char **argv) { srand(time(NULL)); xcb_connection_t *connection = xcb_connect(NULL, NULL); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; xcb_colormap_t colormap = screen->default_colormap; xcb_drawable_t window = xcb_generate_id(connection); uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; uint32_t values[] = {screen->black_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS}; xcb_create_window(connection, /*screen->root_depth,*/ 24, window, screen->root, 0, 0, WIDTH, HEIGHT, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); xcb_pixmap_t pixmap = xcb_generate_id(connection); xcb_create_pixmap(connection, 24, pixmap, window, WIDTH, HEIGHT); uint8_t *img = malloc(WIDTH * HEIGHT * 4); uint8_t *limg = img; /*for (int y = 0; y < HEIGHT; y++)*/ /*for (int x = 0; x < WIDTH; x++) {*/ /**(limg++) = 128;*/ /**(limg++) = 128;*/ /**(limg++) = 128;*/ /*limg++;*/ /*}*/ perlin(img, WIDTH, HEIGHT); xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 24, 32, 0, /*xcb_get_setup(connection)->image_byte_order,*/ XCB_IMAGE_ORDER_MSB_FIRST, XCB_IMAGE_ORDER_LSB_FIRST, img, WIDTH * HEIGHT * 4, img); xcb_gcontext_t gc = xcb_generate_id(connection); xcb_create_gc(connection, gc, pixmap, 0, NULL); xcb_image_put(connection, pixmap, gc, image, 0, 0, 0); xif_write(image, "test.xif"); xcb_map_window(connection, window); xcb_flush(connection); xcb_generic_event_t *event; xcb_expose_event_t *expose; while ((event = xcb_wait_for_event(connection))) { switch (event->response_type & ~0x80) { case XCB_EXPOSE: expose = (xcb_expose_event_t *)event; xcb_copy_area(connection, pixmap, window, gc, expose->x, expose->y, expose->x, expose->y, expose->width, expose->height); xcb_flush(connection); break; case XCB_BUTTON_PRESS: goto end; break; default: break; } free(event); } end: xcb_free_pixmap(connection, pixmap); xcb_disconnect(connection); xcb_image_destroy(image); return 0; }
static void focus (xcb_window_t win, int mode) { uint32_t values[1]; short w, h, b, o; if (!win) return; xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); if (mode == RESIZE) { values[0] = RESIZE_COLOR; xcb_change_window_attributes(conn, win, XCB_CW_BORDER_PIXEL, values); return; } if (!geom) return; w = (short)geom->width; h = (short)geom->height; b = (unsigned short)BORDERWIDTH; o = (unsigned short)OUTER; xcb_rectangle_t inner[] = { /* you're not supposed to understand this. */ { w,0,b-o , h+ b- o}, { w+b +o, 0, b -o, h+ b - o}, { 0,h ,w+b -o,b- o }, { 0,h +b+ o, w+ b- o, b -o}, { w+b+o,b +h +o,b,b} }; xcb_rectangle_t outer[] = { {w + b - o, 0, o, h + b * 2}, {w + b, 0, o, h + b * 2}, {0, h + b - o, w + b * 2, o}, {0, h + b, w + b * 2, o}, {1, 1, 1, 1} }; xcb_pixmap_t pmap = xcb_generate_id(conn); xcb_create_pixmap(conn, scr->root_depth, pmap, win, geom->width + (BORDERWIDTH * 2), geom->height + (BORDERWIDTH * 2)); xcb_gcontext_t gc = xcb_generate_id(conn); xcb_create_gc(conn, gc, pmap, 0, NULL); values[0] = OUTER_COLOR; xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, values); xcb_poly_fill_rectangle(conn, pmap, gc, 5, outer); values[0] = mode ? FOCUSCOL : UNFOCUSCOL; xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, values); xcb_poly_fill_rectangle(conn, pmap, gc, 5, inner); values[0] = pmap; xcb_change_window_attributes(conn, win, XCB_CW_BORDER_PIXMAP, values); if (mode) { xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME); if (win != (*focuswin)) { focus((*focuswin), INACTIVE); (*focuswin) = win; } } xcb_free_pixmap(conn, pmap); xcb_free_gc(conn, gc); }
/* * Creates the config file and tells i3 to reload. * */ static void finish() { printf("creating \"%s\"...\n", config_path); if (!(dpy = XOpenDisplay(NULL))) errx(1, "Could not connect to X11"); FILE *kc_config = fopen(SYSCONFDIR "/i3/config.keycodes", "r"); if (kc_config == NULL) err(1, "Could not open input file \"%s\"", SYSCONFDIR "/i3/config.keycodes"); FILE *ks_config = fopen(config_path, "w"); if (ks_config == NULL) err(1, "Could not open output config file \"%s\"", config_path); free(config_path); char *line = NULL; size_t len = 0; #ifndef USE_FGETLN ssize_t read; #endif bool head_of_file = true; /* write a header about auto-generation to the output file */ fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config); fputs("# It will not be overwritten, so edit it as you like.\n", ks_config); fputs("#\n", ks_config); fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config); fputs("# this file and re-run i3-config-wizard(1).\n", ks_config); fputs("#\n", ks_config); #ifdef USE_FGETLN char *buf = NULL; while ((buf = fgetln(kc_config, &len)) != NULL) { /* fgetln does not return null-terminated strings */ FREE(line); sasprintf(&line, "%.*s", len, buf); #else size_t linecap = 0; while ((read = getline(&line, &linecap, kc_config)) != -1) { len = strlen(line); #endif /* skip the warning block at the beginning of the input file */ if (head_of_file && strncmp("# WARNING", line, strlen("# WARNING")) == 0) continue; head_of_file = false; /* Skip leading whitespace */ char *walk = line; while (isspace(*walk) && walk < (line + len)) { /* Pre-output the skipped whitespaces to keep proper indentation */ fputc(*walk, ks_config); walk++; } /* Set the modifier the user chose */ if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) { if (modifier == MOD_Mod1) fputs("set $mod Mod1\n", ks_config); else fputs("set $mod Mod4\n", ks_config); continue; } /* Check for 'bindcode'. If it’s not a bindcode line, we * just copy it to the output file */ if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) { fputs(walk, ks_config); continue; } char *result = rewrite_binding(walk); fputs(result, ks_config); free(result); } /* sync to do our best in order to have the file really stored on disk */ fflush(ks_config); fsync(fileno(ks_config)); #ifndef USE_FGETLN free(line); #endif fclose(kc_config); fclose(ks_config); /* tell i3 to reload the config file */ int sockfd = ipc_connect(socket_path); ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload"); close(sockfd); exit(0); } int main(int argc, char *argv[]) { config_path = resolve_tilde("~/.i3/config"); socket_path = getenv("I3SOCK"); char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; char *patternbold = "-misc-fixed-bold-r-normal--13-120-75-75-C-70-iso10646-1"; int o, option_index = 0; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; char *options_string = "s:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = strdup(optarg); break; case 'v': printf("i3-config-wizard " I3_VERSION "\n"); return 0; case 'h': printf("i3-config-wizard " I3_VERSION "\n"); printf("i3-config-wizard [-s <socket>] [-v]\n"); return 0; } } /* Check if the destination config file does not exist but the path is * writable. If not, exit now, this program is not useful in that case. */ struct stat stbuf; if (stat(config_path, &stbuf) == 0) { printf("The config file \"%s\" already exists. Exiting.\n", config_path); return 0; } /* Create ~/.i3 if it does not yet exist */ char *config_dir = resolve_tilde("~/.i3"); if (stat(config_dir, &stbuf) != 0) if (mkdir(config_dir, 0755) == -1) err(1, "mkdir(%s) failed", config_dir); free(config_dir); int fd; if ((fd = open(config_path, O_CREAT | O_RDWR, 0644)) == -1) { printf("Cannot open file \"%s\" for writing: %s. Exiting.\n", config_path, strerror(errno)); return 0; } close(fd); unlink(config_path); if (socket_path == NULL) socket_path = root_atom_contents("I3_SOCKET_PATH"); if (socket_path == NULL) socket_path = "/tmp/i3-ipc.sock"; int screens; if ((conn = xcb_connect(NULL, &screens)) == NULL || xcb_connection_has_error(conn)) errx(1, "Cannot open display\n"); xcb_get_modifier_mapping_cookie_t modmap_cookie; modmap_cookie = xcb_get_modifier_mapping(conn); symbols = xcb_key_symbols_alloc(conn); /* Place requests for the atoms we need as soon as possible */ #define xmacro(atom) \ xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); #include "atoms.xmacro" #undef xmacro root_screen = xcb_aux_get_screen(conn, screens); root = root_screen->root; if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL))) errx(EXIT_FAILURE, "Could not get modifier mapping\n"); xcb_numlock_mask = get_mod_mask_for(XCB_NUM_LOCK, symbols, modmap_reply); font = load_font(pattern, true); bold_font = load_font(patternbold, true); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ 490, 297, 300, 205, /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS }); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Setup NetWM atoms */ #define xmacro(name) \ do { \ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \ if (!reply) \ errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \ \ A_ ## name = reply->atom; \ free(reply); \ } while (0); #include "atoms.xmacro" #undef xmacro /* Set dock mode */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_WINDOW_TYPE, A_ATOM, 32, 1, (unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG); /* Set window title */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3: first configuration"), "i3: first configuration"); /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, 500); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ xcb_flush(conn); /* Try (repeatedly, if necessary) to grab the keyboard. We might not * get the keyboard at the first attempt because of the keybinding * still being active when started via a wm’s keybinding. */ xcb_grab_keyboard_cookie_t cookie; xcb_grab_keyboard_reply_t *reply = NULL; int count = 0; while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); reply = xcb_grab_keyboard_reply(conn, cookie, NULL); usleep(1000); } if (reply->status != XCB_GRAB_STATUS_SUCCESS) { fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); exit(-1); } xcb_flush(conn); xcb_generic_event_t *event; while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t*)event); break; /* TODO: handle mappingnotify */ case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t*)event); break; case XCB_EXPOSE: handle_expose(); break; } free(event); } return 0; }
/** * Probe the X server. */ static int Open (vlc_object_t *obj) { vout_display_t *vd = (vout_display_t *)obj; vout_display_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; vd->sys = p_sys; p_sys->pool = NULL; /* Get window, connect to X server */ const xcb_screen_t *scr; p_sys->embed = GetWindow (vd, &p_sys->conn, &scr, &(uint8_t){ 0 }); if (p_sys->embed == NULL) { free (p_sys); return VLC_EGENERIC; } const xcb_setup_t *setup = xcb_get_setup (p_sys->conn); p_sys->byte_order = setup->image_byte_order; /* Determine our pixel format */ xcb_visualid_t vid = 0; p_sys->depth = 0; for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup), *end = fmt + xcb_setup_pixmap_formats_length (setup); fmt < end; fmt++) { if (fmt->depth <= p_sys->depth) continue; /* no better than earlier format */ video_format_t fmt_pic = vd->fmt; /* Check that the pixmap format is supported by VLC. */ switch (fmt->depth) { case 32: if (fmt->bits_per_pixel != 32) continue; #ifdef FIXED_VLC_RGBA_MASK fmt_pic.i_chroma = VLC_CODEC_RGBA; break; #else msg_Dbg (vd, "X11 visual with alpha-channel not supported"); continue; #endif case 24: if (fmt->bits_per_pixel == 32) fmt_pic.i_chroma = VLC_CODEC_RGB32; else if (fmt->bits_per_pixel == 24) fmt_pic.i_chroma = VLC_CODEC_RGB24; else continue; break; case 16: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB16; break; case 15: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB15; break; case 8: if (fmt->bits_per_pixel != 8) continue; fmt_pic.i_chroma = VLC_CODEC_RGB8; break; default: continue; } /* VLC pads lines to 16 pixels internally */ if ((fmt->bits_per_pixel << 4) % fmt->scanline_pad) continue; /* Byte sex is a non-issue for 8-bits. It can be worked around with * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */ if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER) continue; /* Check that the selected screen supports this depth */ const xcb_depth_t *d = FindDepth (scr, fmt->depth); if (d == NULL) continue; /* Find a visual type for the selected depth */ const xcb_visualtype_t *vt = xcb_depth_visuals (d); /* First try True Color class */ for (int i = xcb_depth_visuals_length (d); i > 0; i--) { if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR) { fmt_pic.i_rmask = vt->red_mask; fmt_pic.i_gmask = vt->green_mask; fmt_pic.i_bmask = vt->blue_mask; goto found_visual; } vt++; } /* Then try Static Gray class */ if (fmt->depth == 8) for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--) { if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY) goto found_grey; vt++; } continue; /* Fail: unusable pixel format */ found_grey: fmt_pic.i_chroma = VLC_CODEC_GREY; found_visual: p_sys->bpp = fmt->bits_per_pixel; p_sys->pad = fmt->scanline_pad; p_sys->depth = fmt->depth; vd->fmt = fmt_pic; vid = vt->visual_id; } if (!vid) { msg_Err (obj, "no supported pixel format & visual"); goto error; } msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid); msg_Dbg (vd, " %"PRIu8" bits depth", p_sys->depth); msg_Dbg (vd, " %"PRIu8" bits per pixel", p_sys->bpp); msg_Dbg (vd, " %"PRIu8" bits line pad", p_sys->pad); /* Create colormap (needed to select non-default visual) */ xcb_colormap_t cmap; if (vid != scr->root_visual) { cmap = xcb_generate_id (p_sys->conn); xcb_create_colormap (p_sys->conn, XCB_COLORMAP_ALLOC_NONE, cmap, scr->root, vid); } else cmap = scr->default_colormap; /* Create window */ unsigned width, height; if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height)) goto error; p_sys->window = xcb_generate_id (p_sys->conn); p_sys->gc = xcb_generate_id (p_sys->conn); xcb_pixmap_t pixmap = xcb_generate_id (p_sys->conn); { const uint32_t mask = XCB_CW_BACK_PIXMAP | XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; const uint32_t values[] = { /* XCB_CW_BACK_PIXMAP */ pixmap, /* XCB_CW_BACK_PIXEL */ scr->black_pixel, /* XCB_CW_BORDER_PIXMAP */ pixmap, /* XCB_CW_BORDER_PIXEL */ scr->black_pixel, /* XCB_CW_EVENT_MASK */ XCB_EVENT_MASK_VISIBILITY_CHANGE, /* XCB_CW_COLORMAP */ cmap, }; xcb_void_cookie_t c; xcb_create_pixmap (p_sys->conn, p_sys->depth, pixmap, scr->root, 1, 1); c = xcb_create_window_checked (p_sys->conn, p_sys->depth, p_sys->window, p_sys->embed->handle.xid, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vid, mask, values); xcb_map_window (p_sys->conn, p_sys->window); /* Create graphic context (I wonder why the heck do we need this) */ xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL); if (CheckError (vd, p_sys->conn, "cannot create X11 window", c)) goto error; } msg_Dbg (vd, "using X11 window %08"PRIx32, p_sys->window); msg_Dbg (vd, "using X11 graphic context %08"PRIx32, p_sys->gc); p_sys->cursor = CreateBlankCursor (p_sys->conn, scr); p_sys->visible = false; CheckSHM (obj, p_sys->conn, &p_sys->shm); /* */ vout_display_info_t info = vd->info; info.has_pictures_invalid = true; /* Setup vout_display_t once everything is fine */ vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; /* */ vout_display_SendEventFullscreen (vd, false); vout_display_SendEventDisplaySize (vd, width, height, false); return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
//Output X11Output::X11Output(X11Backend& backend, unsigned int id, const nytl::Vec2i& pos, const nytl::Vec2ui& size) : Output(backend.compositor(), id, pos, size), backend_(&backend) { xcb_connection_t* connection = backend.xConnection(); xcb_screen_t* screen = backend.xScreen(); unsigned int mask = XCB_CW_EVENT_MASK; unsigned int values = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; xWindow_ = xcb_generate_id(connection); xcb_create_window(connection, XCB_COPY_FROM_PARENT, xWindow_, screen->root, 0, 0, size_.x, size_.y ,10, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, &values); if(!xWindow_) { throw std::runtime_error("could not create xcb window"); return; } xcb_change_property(connection, XCB_PROP_MODE_REPLACE, xWindow_, atoms::protocols, XCB_ATOM_ATOM, 32, 1, &atoms::deleteWindow); //cant be resized xcb_size_hints_t sizeHints; sizeHints.max_width = size_.x; sizeHints.max_height = size_.y; sizeHints.min_width = size_.x; sizeHints.min_height = size_.y; sizeHints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE; xcb_icccm_set_wm_size_hints(connection, xWindow_, XCB_ATOM_WM_NORMAL_HINTS, &sizeHints); //no mouse cursor xcb_pixmap_t cursorPixmap = xcb_generate_id(connection); xcb_create_pixmap(connection, 1, cursorPixmap, xWindow_, 1, 1); xcb_cursor_t hiddenCursor = xcb_generate_id(connection); xcb_create_cursor(connection, hiddenCursor, cursorPixmap, cursorPixmap, 0, 0, 0, 0, 0, 0, 0, 0); xcb_free_pixmap(connection, cursorPixmap); xcb_change_window_attributes(connection, xWindow_, XCB_CW_CURSOR, &hiddenCursor); xcb_map_window(connection, xWindow_); //EGL if(!backend.eglContext()) { throw std::runtime_error("x11Output::x11Output: backend ha no valid eglcontext"); return; } eglSurface_ = backend.eglContext()->createSurface(xWindow_); if(!eglSurface_) { throw std::runtime_error("x11Output::x11Output: failed to create egl surface"); return; } drawContext_ = std::make_unique<ny::GlDrawContext>(); if(!drawContext_) { throw std::runtime_error("x11Output::x11Output: failed to create ny::GlesDC"); return; } }
XR_Font_Surface * _xre_xcb_font_surface_new(Ximage_Info *xinf, RGBA_Font_Glyph *fg) { char buf[256]; char buf2[256]; uint32_t values[3]; XR_Font_Surface *fs; DATA8 *data; Ximage_Image *xim; Eina_Hash *pool; uint32_t mask; int w; int h; int pitch; data = fg->glyph_out->bitmap.buffer; w = fg->glyph_out->bitmap.width; h = fg->glyph_out->bitmap.rows; pitch = fg->glyph_out->bitmap.pitch; if (pitch < w) pitch = w; if ((w <= 0) || (h <= 0)) return NULL; if (fg->ext_dat) { fs = fg->ext_dat; if ((fs->xinf->x11.connection == xinf->x11.connection) && (fs->xinf->x11.root == xinf->x11.root)) return fs; snprintf(buf, sizeof(buf), "@%p@/@%x@", fs->xinf->x11.connection, fs->xinf->x11.root); pool = eina_hash_find(_xr_fg_pool, buf); if (pool) { snprintf(buf, sizeof(buf), "%p", fg); fs = eina_hash_find(pool, buf); if (fs) return fs; } } fs = calloc(1, sizeof(XR_Font_Surface)); if (!fs) return NULL; fs->xinf = xinf; fs->fg = fg; fs->xinf->references++; fs->w = w; fs->h = h; snprintf(buf, sizeof(buf), "@%p@/@%x@", fs->xinf->x11.connection, fs->xinf->x11.root); pool = eina_hash_find(_xr_fg_pool, buf); if (!pool) pool = eina_hash_string_superfast_new(NULL); snprintf(buf2, sizeof(buf2), "%p", fg); eina_hash_add(pool, buf2, fs); if (!_xr_fg_pool) _xr_fg_pool = eina_hash_string_superfast_new(NULL); eina_hash_add(_xr_fg_pool, buf, pool); fs->draw = xcb_generate_id(xinf->x11.connection); xcb_create_pixmap(xinf->x11.connection, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->depth, fs->draw, xinf->x11.root, w, h); mask = XCB_RENDER_CP_REPEAT | XCB_RENDER_CP_DITHER | XCB_RENDER_CP_COMPONENT_ALPHA; values[0] = 0; values[1] = 0; values[2] = 0; fs->pic = xcb_generate_id(xinf->x11.connection); xcb_render_create_picture(xinf->x11.connection, fs->pic, fs->draw, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->id, mask, values); xim = _xr_xcb_image_new(fs->xinf, w, h, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->depth); if ((fg->glyph_out->bitmap.num_grays == 256) && (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)) { int x, y; DATA8 *p1, *p2; for (y = 0; y < h; y++) { p1 = data + (pitch * y); p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y); for (x = 0; x < w; x++) { *p2 = *p1; p1++; p2++; } } } else { DATA8 *tmpbuf = NULL, *dp, *tp, bits; int bi, bj, end; const DATA8 bitrepl[2] = {0x0, 0xff}; tmpbuf = alloca(w); { int x, y; DATA8 *p1, *p2; for (y = 0; y < h; y++) { p1 = tmpbuf; p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y); tp = tmpbuf; dp = data + (y * fg->glyph_out->bitmap.pitch); for (bi = 0; bi < w; bi += 8) { bits = *dp; if ((w - bi) < 8) end = w - bi; else end = 8; for (bj = 0; bj < end; bj++) { *tp = bitrepl[(bits >> (7 - bj)) & 0x1]; tp++; } dp++; } for (x = 0; x < w; x++) { *p2 = *p1; p1++; p2++; } } } } _xr_xcb_image_put(xim, fs->draw, 0, 0, w, h); return fs; }
void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window) { xcb_get_geometry_cookie_t get_geometry_cookie; xcb_get_geometry_reply_t *get_geometry_reply; assert (osd); lprintf("drawable changed\n"); /* Do I need to recreate the GC's?? XFreeGC (osd->display, osd->gc); XFreeGC (osd->display, osd->mask_gc); XFreeGC (osd->display, osd->mask_gc_back); */ xcb_free_pixmap(osd->connection, osd->bitmap); xcb_free_colormap(osd->connection, osd->cmap); /* we need to call XSync(), because otherwise, calling XDestroyWindow() on the parent window could destroy our OSD window twice !! */ /* XSync (osd->display, False); FIXME don't think that we need that --pfister */ osd->window = window; get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window); get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL); osd->depth = get_geometry_reply->depth; osd->width = get_geometry_reply->width; osd->height = get_geometry_reply->height; free(get_geometry_reply); assert(osd->width); assert(osd->height); switch(osd->mode) { case XCBOSD_SHAPED: { xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap); xcb_destroy_window(osd->connection, osd->u.shaped.window); unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE }; osd->u.shaped.window = xcb_generate_id(osd->connection); xcb_create_window(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window, osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, window_params); osd->u.shaped.mapped = 0; osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection); xcb_create_pixmap(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height); osd->bitmap = xcb_generate_id(osd->connection); xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height); osd->cmap = xcb_generate_id(osd->connection); xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual); break; } case XCBOSD_COLORKEY: osd->bitmap = xcb_generate_id(osd->connection); xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height); osd->cmap = xcb_generate_id(osd->connection); xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual); break; } osd->clean = UNDEFINED; /* do not xcbosd_clear() here: osd->u.colorkey.sc has not being updated yet */ }
xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode) { xcbosd *osd; xcb_get_geometry_cookie_t get_geometry_cookie; xcb_get_geometry_reply_t *get_geometry_reply; xcb_void_cookie_t generic_cookie; xcb_generic_error_t *generic_error; osd = calloc(1, sizeof(xcbosd)); if (!osd) return NULL; osd->mode = mode; osd->xine = xine; osd->connection = connection; osd->screen = screen; osd->window = window; osd->visual = osd->screen->root_visual; get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window); get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL); osd->depth = get_geometry_reply->depth; osd->width = get_geometry_reply->width; osd->height = get_geometry_reply->height; free(get_geometry_reply); assert(osd->width); assert(osd->height); switch (mode) { case XCBOSD_SHAPED: { const xcb_query_extension_reply_t *query_extension_reply = xcb_get_extension_data(osd->connection, &xcb_shape_id); if (!query_extension_reply || !query_extension_reply->present) { xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: XShape extension not available. unscaled overlay disabled.\n")); goto error2; } unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE }; osd->u.shaped.window = xcb_generate_id(osd->connection); generic_cookie = xcb_create_window_checked(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window, osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, window_params); generic_error = xcb_request_check(osd->connection, generic_cookie); if (generic_error != NULL) { xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating window. unscaled overlay disabled.\n")); free(generic_error); goto error_window; } osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection); generic_cookie = xcb_create_pixmap_checked(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height); generic_error = xcb_request_check(osd->connection, generic_cookie); if (generic_error != NULL) { xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating pixmap. unscaled overlay disabled.\n")); free(generic_error); goto error_aftermaskbitmap; } osd->bitmap = xcb_generate_id(osd->connection); xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height); osd->gc = xcb_generate_id(osd->connection); xcb_create_gc(osd->connection, osd->gc, osd->u.shaped.window, 0, NULL); osd->u.shaped.mask_gc = xcb_generate_id(osd->connection); xcb_create_gc(osd->connection, osd->u.shaped.mask_gc, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->white_pixel); osd->u.shaped.mask_gc_back = xcb_generate_id(osd->connection); xcb_create_gc(osd->connection, osd->u.shaped.mask_gc_back, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->black_pixel); osd->u.shaped.mapped = 0; osd->cmap = xcb_generate_id(osd->connection); xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual); break; } case XCBOSD_COLORKEY: osd->bitmap = xcb_generate_id(osd->connection); xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height); osd->gc = xcb_generate_id(osd->connection); xcb_create_gc(osd->connection, osd->gc, osd->window, 0, NULL); osd->cmap = xcb_generate_id(osd->connection); xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual); /* FIXME: the expose event doesn't seem to happen? */ /*XSelectInput (osd->display, osd->window, ExposureMask);*/ break; default: goto error2; } osd->clean = UNDEFINED; xcbosd_expose(osd); xprintf(osd->xine, XINE_VERBOSITY_DEBUG, _("x11osd: unscaled overlay created (%s mode).\n"), (mode==XCBOSD_SHAPED) ? "XShape" : "Colorkey" ); return osd; /* XFreeGC (osd->display, osd->gc); XFreeGC (osd->display, osd->mask_gc); XFreeGC (osd->display, osd->mask_gc_back); */ error_aftermaskbitmap: if(mode==XCBOSD_SHAPED) xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap); error_window: if(mode==XCBOSD_SHAPED) xcb_destroy_window(osd->connection, osd->u.shaped.window); error2: free (osd); return NULL; }
static void get_resources (el_backend_x11_t self) { #define F(field) offsetof(struct el_backend_x11, field) static const struct { const char* name; int offset; } atoms[] = { { "WM_PROTOCOLS", F(atom.wm_protocols) }, { "WM_NORMAL_HINTS", F(atom.wm_normal_hints) }, { "WM_SIZE_HINTS", F(atom.wm_size_hints) }, { "WM_DELETE_WINDOW", F(atom.wm_delete_window) }, { "WM_CLASS", F(atom.wm_class) }, { "_NET_WM_NAME", F(atom.net_wm_name) }, { "_NET_WM_ICON", F(atom.net_wm_icon) }, { "_NET_WM_STATE", F(atom.net_wm_state) }, { "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) }, { "_NET_SUPPORTING_WM_CHECK", F(atom.net_supporting_wm_check) }, { "_NET_SUPPORTED", F(atom.net_supported) }, { "_XKB_RULES_NAMES", F(atom.xkb_names) }, { "STRING", F(atom.string) }, { "UTF8_STRING", F(atom.utf8_string) }, { "CARDINAL", F(atom.cardinal) }, }; #undef F uint8_t data[] = { 0, 0, 0, 0 }; xcb_intern_atom_cookie_t cookies[lengthof(atoms)]; for (size_t i = 0; i < lengthof(atoms); i++) { cookies[i] = xcb_intern_atom(self->connection, 0, strlen(atoms[i].name), atoms[i].name); } for (size_t i = 0; i < lengthof(atoms); i++) { xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(self->connection, cookies[i], NULL); *(xcb_atom_t*) ((char*) self + atoms[i].offset) = reply->atom; free(reply); } xcb_pixmap_t pixmap = xcb_generate_id(self->connection); xcb_gc_t gc = xcb_generate_id(self->connection); xcb_create_pixmap(self->connection, 1, pixmap, self->screen->root, 1, 1); xcb_create_gc(self->connection, gc, pixmap, 0, NULL); xcb_put_image(self->connection, XCB_IMAGE_FORMAT_XY_PIXMAP, pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof(data), data); self->cursor = xcb_generate_id(self->connection); xcb_create_cursor(self->connection, self->cursor, pixmap, pixmap, 0, 0, 0, 0, 0, 0, 1, 1); xcb_free_gc(self->connection, gc); xcb_free_pixmap(self->connection, pixmap); }
/** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, void *native_surface, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_generic_error_t *error; const __DRIconfig *config; (void) drv; dri2_surf = malloc(sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false, native_surface)) goto cleanup_surf; dri2_surf->region = XCB_NONE; if (type == EGL_PBUFFER_BIT) { dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, dri2_surf->drawable, dri2_dpy->screen->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); dri2_surf->drawable = (uintptr_t) native_surface; } config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace); if (!config) { _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); goto cleanup_pixmap; } if (dri2_dpy->dri2) { dri2_surf->dri_drawable = dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, dri2_surf); } else { assert(dri2_dpy->swrast); dri2_surf->dri_drawable = dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, config, dri2_surf); } if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); if (error != NULL) { if (error->error_code == BadAlloc) _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); else if (type == EGL_WINDOW_BIT) _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_get_geometry"); else _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry"); free(error); goto cleanup_dri_drawable; } else if (reply == NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); goto cleanup_dri_drawable; } dri2_surf->base.Width = reply->width; dri2_surf->base.Height = reply->height; dri2_surf->depth = reply->depth; free(reply); } if (dri2_dpy->dri2) { xcb_void_cookie_t cookie; int conn_error; cookie = xcb_dri2_create_drawable_checked(dri2_dpy->conn, dri2_surf->drawable); error = xcb_request_check(dri2_dpy->conn, cookie); conn_error = xcb_connection_has_error(dri2_dpy->conn); if (conn_error || error != NULL) { if (type == EGL_PBUFFER_BIT || conn_error || error->error_code == BadAlloc) _eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked"); else if (type == EGL_WINDOW_BIT) _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_dri2_create_drawable_checked"); else _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_dri2_create_drawable_checked"); free(error); goto cleanup_dri_drawable; } } else { if (type == EGL_PBUFFER_BIT) { dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE); } swrastCreateDrawable(dri2_dpy, dri2_surf); } /* we always copy the back buffer to front */ dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; return &dri2_surf->base; cleanup_dri_drawable: dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); cleanup_pixmap: if (type == EGL_PBUFFER_BIT) xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); cleanup_surf: free(dri2_surf); return NULL; }
/* Main driver */ int main (int argc, char **argv) { xcb_connection_t *conn; int conn_screen; xcb_screen_t *root_screen; xcb_drawable_t root_window; xcb_connection_t *conn_two; int conn_two_screen; xcb_screen_t *root_two_screen; xcb_drawable_t root_two_window; xcb_drawable_t window; uint32_t mask; uint32_t values[1]; xcb_void_cookie_t cookie; xcb_get_geometry_reply_t *geom_reply; xcb_generic_event_t *event; image_data_t img_data; xcb_image_t *image; xcb_pixmap_t pixmap; xcb_gcontext_t gc; /* Check the first argument to see what display to connect to. If empty, then use default display. */ if (argc > 1) { conn = xcb_connect(argv[1], &conn_screen); } else { conn = xcb_connect(NULL, &conn_screen); } root_screen = xcb_aux_get_screen(conn, conn_screen); root_window = root_screen->root; /* Get the geometry of the root window */ geom_reply = GetWindowGeometry(conn, root_window); WriteWindowInfo(conn, root_window); WriteAllChildrenWindowInfo(conn, root_window); img_data = GetWindowImageData(conn, root_window); xcb_flush(conn); /* Get the image of the root window */ image = xcb_image_get(conn, root_window, geom_reply->x, geom_reply->y, geom_reply->width, geom_reply->height, (unsigned int) ~0L, XCB_IMAGE_FORMAT_Z_PIXMAP); /* Set up the events the window will recognize */ mask = XCB_CW_EVENT_MASK; values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; /* Create our new window on the default display. Make it half the size */ conn_two = xcb_connect(NULL, &conn_two_screen); root_two_screen = xcb_aux_get_screen(conn_two, conn_two_screen); root_two_window = root_two_screen->root; window = xcb_generate_id(conn_two); cookie = xcb_create_window_checked(conn_two, XCB_COPY_FROM_PARENT, window, root_two_window, geom_reply->x, geom_reply->y, geom_reply->width / 2, geom_reply->height / 2, geom_reply->border_width, XCB_WINDOW_CLASS_INPUT_OUTPUT, root_two_screen->root_visual, mask, values); if (RequestCheck(conn_two, cookie, "Falied to create new window")) { exit(1); } WriteWindowInfo(conn_two, window); /* Map the window and flush the connection so it draws to the screen */ xcb_map_window(conn_two, window); xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Create the pixmap and associate it with our new window. */ pixmap = xcb_generate_id(conn_two); cookie = xcb_create_pixmap(conn_two, geom_reply->depth, pixmap, window, geom_reply->width, geom_reply->height); if (RequestCheck(conn_two, cookie, "Failed to create pixmap")) { exit(1); } /* Put the root_window image into the pixmap. Note that a gc is * created, but I believe it is ignored. */ gc = xcb_generate_id(conn_two); xcb_create_gc(conn_two, gc, window, 0, 0); cookie = xcb_image_put(conn_two, pixmap, gc, image, 0, 0, 0); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } /* Copy the pixmap into the new window */ cookie = xcb_copy_area(conn_two, pixmap, window, gc, 0, 0, 0, 0, geom_reply->width / 2, geom_reply->height / 2); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Enter infinte loop so the window stays open */ while (1) { } /* Never get here, but if we could, would still want to clean up memory */ free(geom_reply); xcb_disconnect(conn); xcb_disconnect(conn_two); return 0; }
/** * Processing callback */ static void Demux (void *data) { demux_t *demux = data; demux_sys_t *sys = demux->p_sys; xcb_connection_t *conn = sys->conn; /* Determine capture region */ xcb_get_geometry_cookie_t gc; xcb_query_pointer_cookie_t qc; gc = xcb_get_geometry (conn, sys->window); if (sys->follow_mouse) qc = xcb_query_pointer (conn, sys->window); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window); discard: if (sys->follow_mouse) xcb_discard_reply (conn, gc.sequence); return; } int w = sys->w; int h = sys->h; int x, y; if (sys->follow_mouse) { xcb_query_pointer_reply_t *ptr = xcb_query_pointer_reply (conn, qc, NULL); if (ptr == NULL) { free (geo); return; } if (w == 0 || w > geo->width) w = geo->width; x = ptr->win_x; if (x < w / 2) x = 0; else if (x >= (int)geo->width - (w / 2)) x = geo->width - w; else x -= w / 2; if (h == 0 || h > geo->height) h = geo->height; y = ptr->win_y; if (y < h / 2) y = 0; else if (y >= (int)geo->height - (h / 2)) y = geo->height - h; else y -= h / 2; } else { int max; x = sys->x; max = (int)geo->width - x; if (max <= 0) goto discard; if (w == 0 || w > max) w = max; y = sys->y; max = (int)geo->height - y; if (max <= 0) goto discard; if (h == 0 || h > max) h = max; } /* Update elementary stream format (if needed) */ if (w != sys->cur_w || h != sys->cur_h) { if (sys->es != NULL) es_out_Del (demux->out, sys->es); /* Update composite pixmap */ if (sys->window != geo->root) { xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */ xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap); xcb_create_pixmap (conn, geo->depth, sys->pixmap, geo->root, geo->width, geo->height); } sys->es = InitES (demux, w, h, geo->depth); if (sys->es != NULL) { sys->cur_w = w; sys->cur_h = h; } } /* Capture screen */ xcb_drawable_t drawable = (sys->window != geo->root) ? sys->pixmap : sys->window; free (geo); xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, x, y, w, h, ~0), NULL); if (img == NULL) return; block_t *block = block_heap_Alloc (img, xcb_get_image_data (img), xcb_get_image_data_length (img)); if (block == NULL) return; /* Send block - zero copy */ if (sys->es != NULL) { if (sys->pts == VLC_TS_INVALID) sys->pts = mdate (); block->i_pts = block->i_dts = sys->pts; es_out_Control (demux->out, ES_OUT_SET_PCR, sys->pts); es_out_Send (demux->out, sys->es, block); sys->pts += sys->interval; } }
void x_client_icon::update_wm_hints_icon(void) { xcb_free_pixmap(m_c(), m_wm_hints_icon); m_wm_hints_icon = XCB_NONE; xcb_generic_error_t * error; xcb_get_property_cookie_t c = xcb_icccm_get_wm_hints(m_c(), m_x_client.window()); xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error); if (error) { std::free(error); } else { xcb_icccm_wm_hints_t wm_hints; xcb_icccm_get_wm_hints_from_reply(&wm_hints, r); if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP) { unsigned int width, height; { Window root; int x, y; unsigned int border_width, depth; XGetGeometry(m_c.dpy(), wm_hints.icon_pixmap, &root, &x, &y, &width, &height, &border_width, &depth); m_icon_geometry.first = width; m_icon_geometry.second = height; } xcb_image_t * icon_rgb = xcb_image_get(m_c(), wm_hints.icon_pixmap, 0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP); xcb_image_t * icon_mask; if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_MASK) { icon_mask = xcb_image_get(m_c(), wm_hints.icon_mask, 0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP); } else { icon_mask = xcb_image_create_native( m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL); std::memset(icon_mask->data, 0xff, width * height * (icon_mask->bpp / icon_mask->stride)); } xcb_image_t * icon_rgba = xcb_image_create_native( m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL); for (std::size_t x = 0; x < width; ++x) { for (std::size_t y = 0; y < height; ++y) { uint32_t rgba = 0; if (xcb_image_get_pixel(icon_mask, x, y)) { uint32_t rgb = xcb_image_get_pixel(icon_rgb, x, y); uint8_t * s = (uint8_t *)&rgb; uint8_t * d = (uint8_t *)&rgba; d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = 0xff; } xcb_image_put_pixel(icon_rgba, x, y, rgba); } } m_wm_hints_icon = xcb_generate_id(m_c()); xcb_create_pixmap( m_c(), 32, m_wm_hints_icon, m_c.root_window(), width, height); xcb_gcontext_t gc = xcb_generate_id(m_c()); xcb_create_gc(m_c(), gc, m_wm_hints_icon, 0, NULL); xcb_image_put(m_c(), m_wm_hints_icon, gc, icon_rgba, 0, 0, 0); xcb_image_destroy(icon_rgb); xcb_image_destroy(icon_mask); xcb_image_destroy(icon_rgba); xcb_free_gc(m_c(), gc); } } if (r) std::free(r); }
QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const { if (width == 0 || height == 0) return QPixmap(); // TODO: handle multiple screens QXcbScreen *screen = const_cast<QXcbScreen *>(this); xcb_window_t root = screen->root(); if (window == 0) window = root; xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), window); xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL); if (!reply) { return QPixmap(); } if (width < 0) width = reply->width - x; if (height < 0) height = reply->height - y; geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), root); xcb_get_geometry_reply_t *root_reply = xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL); if (!root_reply) { free(reply); return QPixmap(); } if (reply->depth == root_reply->depth) { // if the depth of the specified window and the root window are the // same, grab pixels from the root window (so that we get the any // overlapping windows and window manager frames) // map x and y to the root window xcb_translate_coordinates_cookie_t translate_cookie = xcb_translate_coordinates_unchecked(xcb_connection(), window, root, x, y); xcb_translate_coordinates_reply_t *translate_reply = xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL); if (!translate_reply) { free(reply); free(root_reply); return QPixmap(); } x = translate_reply->dst_x; y = translate_reply->dst_y; window = root; free(translate_reply); free(reply); reply = root_reply; } else { free(root_reply); root_reply = 0; } xcb_get_window_attributes_reply_t *attributes_reply = xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL); if (!attributes_reply) { free(reply); return QPixmap(); } const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); free(attributes_reply); xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection()); xcb_create_pixmap(xcb_connection(), reply->depth, pixmap, window, width, height); uint32_t gc_value_mask = XCB_GC_SUBWINDOW_MODE; uint32_t gc_value_list[] = { XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS }; xcb_gcontext_t gc = xcb_generate_id(xcb_connection()); xcb_create_gc(xcb_connection(), gc, pixmap, gc_value_mask, gc_value_list); xcb_copy_area(xcb_connection(), window, pixmap, gc, x, y, 0, 0, width, height); QPixmap result = qt_xcb_pixmapFromXPixmap(connection(), pixmap, width, height, reply->depth, visual); free(reply); xcb_free_gc(xcb_connection(), gc); xcb_free_pixmap(xcb_connection(), pixmap); return result; }
int main(int argc, char **argv) { xcb_connection_t *connection = xcb_connect(NULL, NULL); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; uint32_t mask = XCB_CW_BACK_PIXEL; uint32_t values[] = {screen->black_pixel}; xcb_drawable_t window = xcb_generate_id(connection); xcb_create_window(connection, 24, window, screen->root, 0, 0, WIDTH, HEIGHT, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(argv[0]), argv[0]); xcb_pixmap_t pixmap = xcb_generate_id(connection); xcb_create_pixmap(connection, 24, pixmap, window, WIDTH, HEIGHT); uint8_t *img = malloc(WIDTH * HEIGHT * 4); xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 24, 32, 0, XCB_IMAGE_ORDER_MSB_FIRST, XCB_IMAGE_ORDER_LSB_FIRST, img, WIDTH * HEIGHT * 4, img); mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; values[0] = screen->black_pixel; values[1] = 0xFFFFFF; xcb_gcontext_t gc = xcb_generate_id(connection); xcb_create_gc(connection, gc, pixmap, mask, values); xcb_image_put(connection, pixmap, gc, image, 0, 0, 0); xcb_map_window(connection, window); xcb_flush(connection); uint8_t value = 0; uint32_t *limg; Gol *gol = gol_new(BOARD_WIDTH, BOARD_HEIGHT); gol_random(gol, time(NULL)); while (1) { limg = (uint32_t *)image->data; for (int i = 0; i < BOARD_WIDTH * BOARD_HEIGHT; i++) *(limg++) = gol->buffers[gol->front][i] ? 0x00FFFF00 : 0x00000000; xcb_image_put(connection, pixmap, gc, image, 0, 0, 0); xcb_copy_area(connection, pixmap, window, gc, 0, 0, 0, 0, WIDTH, HEIGHT); xcb_flush(connection); value++; gol_simulate(gol); } return 0; }
void draw_byxid(xcb_window_t xid) { xcb_connection_t *c=G.conn; xcb_window_t w=xid; xcb_get_geometry_reply_t *geo; uint32_t mask; uint32_t values[4]; geo = xcb_get_geometry_reply(G.conn, xcb_get_geometry(G.conn, w), NULL); assert(geo != NULL); printf("get (%hdx%hd)@(%dx%d)\n", geo->x, geo->y, geo->width, geo->height); // try require event handler, and draw something. //start create sub window and draw gc in it. // getchar(); /* create sub window */ xcb_window_t child; child = xcb_generate_id(c); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = G.s->black_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; xcb_void_cookie_t cookie; // create colormap if needed , window pixfmt is diff from root window. /* xcb_map_window(c, w); xcb_flush(c); */ //creat a half size window geo->width /=2; geo->height /=2; cookie = xcb_create_window_checked(c, G.s->root_depth, child, w, 10, 10, geo->width, geo->height, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, G.s->root_visual, mask, values); //check cookie error if(1){ xcb_generic_error_t *err; err = xcb_request_check (c, cookie); if (err){ int code = err->error_code; free (err); printf("X11 error %d", code); assert (code != 0); } } xcb_map_window(c, child); xcb_flush(c); // xcb_reparent_window(c, child, 0,100,100); // root=0 return no affected. xcb_reparent_window(c, child, G.s->root,100,100); // xcb_map_window(c, child);xcb_flush(c); // ? why make a pixmap as attribute of new sub window xcb_pixmap_t pixmap; xcb_create_pixmap (G.conn, geo->depth, pixmap, child, geo->width, geo->height); values[1] |= XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE; xcb_change_window_attributes_checked(c, child, mask, values); xcb_flush(c); // xcb_poly_fill_rectangle(c, child, g, 1, &r); // both map and flush need to show window up //getchar(); //unmap is minimum window // xcb_unmap_window(c, child); // xcb_destroy_window(c, child); create_dri_drawable(); int done =0 ; xcb_generic_event_t *e; printf("wait event\n"); while (!done ) { printf("\re=>(x%x)", e->response_type); fflush(stdout); e = xcb_wait_for_event(c); if(!e)printf("wait event error\n"); else{ switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ printf("XCB_EXPOSE\n"); draw_gc(child); break; case XCB_KEY_PRESS: /* exit on key press */ //gwj done = 1; break; } free(e); } } xcb_unmap_window(c, child); xcb_destroy_window(c, child); }
/** * Processing callback */ static void Demux (void *opaque) { demux_t *demux = opaque; demux_sys_t *sys = demux->p_sys; xcb_connection_t *conn = sys->conn; /* Determine capture region */ xcb_get_geometry_cookie_t gc; xcb_query_pointer_cookie_t qc; gc = xcb_get_geometry (conn, sys->window); if (sys->follow_mouse) qc = xcb_query_pointer (conn, sys->window); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window); discard: if (sys->follow_mouse) xcb_discard_reply (conn, gc.sequence); return; } int w = sys->w; int h = sys->h; int x, y; if (sys->follow_mouse) { xcb_query_pointer_reply_t *ptr = xcb_query_pointer_reply (conn, qc, NULL); if (ptr == NULL) { free (geo); return; } if (w == 0 || w > geo->width) w = geo->width; x = ptr->win_x; if (x < w / 2) x = 0; else if (x >= (int)geo->width - (w / 2)) x = geo->width - w; else x -= w / 2; if (h == 0 || h > geo->height) h = geo->height; y = ptr->win_y; if (y < h / 2) y = 0; else if (y >= (int)geo->height - (h / 2)) y = geo->height - h; else y -= h / 2; } else { int max; x = sys->x; max = (int)geo->width - x; if (max <= 0) goto discard; if (w == 0 || w > max) w = max; y = sys->y; max = (int)geo->height - y; if (max <= 0) goto discard; if (h == 0 || h > max) h = max; } /* Update elementary stream format (if needed) */ if (w != sys->cur_w || h != sys->cur_h) { if (sys->es != NULL) es_out_Del (demux->out, sys->es); /* Update composite pixmap */ if (sys->window != geo->root) { xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */ xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap); xcb_create_pixmap (conn, geo->depth, sys->pixmap, geo->root, geo->width, geo->height); } sys->es = InitES (demux, w, h, geo->depth, &sys->bpp); if (sys->es != NULL) { sys->cur_w = w; sys->cur_h = h; sys->bpp /= 8; /* bits -> bytes */ } } /* Capture screen */ xcb_drawable_t drawable = (sys->window != geo->root) ? sys->pixmap : sys->window; free (geo); block_t *block = NULL; #if HAVE_SYS_SHM_H if (sys->shm) { /* Capture screen through shared memory */ size_t size = w * h * sys->bpp; int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); if (id == -1) /* XXX: fallback */ { msg_Err (demux, "shared memory allocation error: %m"); goto noshm; } /* Attach the segment to X and capture */ xcb_shm_get_image_reply_t *img; xcb_shm_get_image_cookie_t ck; xcb_shm_attach (conn, sys->segment, id, 0 /* read/write */); ck = xcb_shm_get_image (conn, drawable, x, y, w, h, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, sys->segment, 0); xcb_shm_detach (conn, sys->segment); img = xcb_shm_get_image_reply (conn, ck, NULL); xcb_flush (conn); /* ensure eventual detach */ if (img == NULL) { shmctl (id, IPC_RMID, 0); goto noshm; } free (img); /* Attach the segment to VLC */ void *shm = shmat (id, NULL, 0 /* read/write */); shmctl (id, IPC_RMID, 0); if (-1 == (intptr_t)shm) { msg_Err (demux, "shared memory attachment error: %m"); return; } block = block_shm_Alloc (shm, size); if (unlikely(block == NULL)) shmdt (shm); } noshm: #endif if (block == NULL) { /* Capture screen through socket (fallback) */ xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, x, y, w, h, ~0), NULL); if (img == NULL) return; uint8_t *data = xcb_get_image_data (img); size_t datalen = xcb_get_image_data_length (img); block = block_heap_Alloc (img, data + datalen - (uint8_t *)img); if (block == NULL) return; block->p_buffer = data; block->i_buffer = datalen; } /* Send block - zero copy */ if (sys->es != NULL) { block->i_pts = block->i_dts = mdate (); es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); es_out_Send (demux->out, sys->es, block); } }
/** * Probe the X server. */ static int Open (vlc_object_t *obj) { vout_display_t *vd = (vout_display_t *)obj; vout_display_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; vd->sys = sys; sys->pool = NULL; /* Get window, connect to X server */ xcb_connection_t *conn; const xcb_screen_t *scr; uint16_t width, height; sys->embed = XCB_parent_Create (vd, &conn, &scr, &width, &height); if (sys->embed == NULL) { free (sys); return VLC_EGENERIC; } sys->conn = conn; const xcb_setup_t *setup = xcb_get_setup (conn); /* Determine our pixel format */ video_format_t fmt_pic; xcb_visualid_t vid; sys->depth = 0; for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup), *end = fmt + xcb_setup_pixmap_formats_length (setup); fmt < end; fmt++) { if (fmt->depth <= sys->depth) continue; /* no better than earlier format */ fmt_pic = vd->fmt; /* Check that the pixmap format is supported by VLC. */ switch (fmt->depth) { case 32: if (fmt->bits_per_pixel != 32) continue; fmt_pic.i_chroma = VLC_CODEC_ARGB; break; case 24: if (fmt->bits_per_pixel == 32) fmt_pic.i_chroma = VLC_CODEC_RGB32; else if (fmt->bits_per_pixel == 24) fmt_pic.i_chroma = VLC_CODEC_RGB24; else continue; break; case 16: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB16; break; case 15: if (fmt->bits_per_pixel != 16) continue; fmt_pic.i_chroma = VLC_CODEC_RGB15; break; case 8: if (fmt->bits_per_pixel != 8) continue; fmt_pic.i_chroma = VLC_CODEC_RGB8; break; default: continue; } /* Byte sex is a non-issue for 8-bits. It can be worked around with * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */ if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER) continue; /* Make sure the X server is sane */ assert (fmt->bits_per_pixel > 0); if (unlikely(fmt->scanline_pad % fmt->bits_per_pixel)) continue; /* Check that the selected screen supports this depth */ const xcb_depth_t *d = FindDepth (scr, fmt->depth); if (d == NULL) continue; /* Find a visual type for the selected depth */ const xcb_visualtype_t *vt = xcb_depth_visuals (d); /* First try True Color class */ for (int i = xcb_depth_visuals_length (d); i > 0; i--) { if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR) { fmt_pic.i_rmask = vt->red_mask; fmt_pic.i_gmask = vt->green_mask; fmt_pic.i_bmask = vt->blue_mask; found_visual: vid = vt->visual_id; msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid); sys->depth = fmt->depth; msg_Dbg (vd, " %"PRIu8" bits depth", sys->depth); msg_Dbg (vd, " %"PRIu8" bits per pixel", fmt->bits_per_pixel); msg_Dbg (vd, " %"PRIu8" bits line pad", fmt->scanline_pad); goto found_format; } vt++; } /* Then try Static Gray class */ if (fmt->depth != 8) continue; vt = xcb_depth_visuals (d); for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--) { if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY) { fmt_pic.i_chroma = VLC_CODEC_GREY; goto found_visual; } vt++; } } msg_Err (obj, "no supported pixel format & visual"); goto error; found_format:; /* Create colormap (needed to select non-default visual) */ xcb_colormap_t cmap; if (vid != scr->root_visual) { cmap = xcb_generate_id (conn); xcb_create_colormap (conn, XCB_COLORMAP_ALLOC_NONE, cmap, scr->root, vid); } else cmap = scr->default_colormap; /* Create window */ sys->window = xcb_generate_id (conn); sys->gc = xcb_generate_id (conn); xcb_pixmap_t pixmap = xcb_generate_id (conn); { const uint32_t mask = XCB_CW_BACK_PIXMAP | XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; const uint32_t values[] = { /* XCB_CW_BACK_PIXMAP */ pixmap, /* XCB_CW_BACK_PIXEL */ scr->black_pixel, /* XCB_CW_BORDER_PIXMAP */ pixmap, /* XCB_CW_BORDER_PIXEL */ scr->black_pixel, /* XCB_CW_EVENT_MASK */ XCB_EVENT_MASK_VISIBILITY_CHANGE, /* XCB_CW_COLORMAP */ cmap, }; xcb_void_cookie_t c; xcb_create_pixmap (conn, sys->depth, pixmap, scr->root, 1, 1); c = xcb_create_window_checked (conn, sys->depth, sys->window, sys->embed->handle.xid, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vid, mask, values); xcb_map_window (conn, sys->window); /* Create graphic context (I wonder why the heck do we need this) */ xcb_create_gc (conn, sys->gc, sys->window, 0, NULL); if (XCB_error_Check (vd, conn, "cannot create X11 window", c)) goto error; } msg_Dbg (vd, "using X11 window %08"PRIx32, sys->window); msg_Dbg (vd, "using X11 graphic context %08"PRIx32, sys->gc); sys->cursor = XCB_cursor_Create (conn, scr); sys->visible = false; if (XCB_shm_Check (obj, conn)) { sys->seg_base = xcb_generate_id (conn); for (unsigned i = 1; i < MAX_PICTURES; i++) xcb_generate_id (conn); } else sys->seg_base = 0; /* Setup vout_display_t once everything is fine */ vd->info.has_pictures_invalid = true; vd->info.has_event_thread = true; vd->fmt = fmt_pic; vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; /* */ bool is_fullscreen = vd->cfg->is_fullscreen; if (is_fullscreen && vout_window_SetFullScreen (sys->embed, true)) is_fullscreen = false; vout_display_SendEventFullscreen (vd, is_fullscreen); vout_display_SendEventDisplaySize (vd, width, height, is_fullscreen); return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
void NonCompositedOutlineVisual::show() { if (!m_initialized) { const QRect geo(0, 0, 1, 1); const uint32_t values[] = {true}; // TODO: use template variant m_leftOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); m_rightOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); m_topOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); m_bottomOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); m_initialized = true; } const int defaultDepth = Xcb::defaultDepth(); const QRect &outlineGeometry = outline()->geometry(); // left/right parts are between top/bottom, they don't reach as far as the corners const uint16_t verticalWidth = 5; const uint16_t verticalHeight = outlineGeometry.height() - 10; const uint16_t horizontalWidth = outlineGeometry.width(); const uint horizontalHeight = 5; m_leftOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + 5, verticalWidth, verticalHeight); m_rightOutline.setGeometry(outlineGeometry.x() + outlineGeometry.width() - 5, outlineGeometry.y() + 5, verticalWidth, verticalHeight); m_topOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y(), horizontalWidth, horizontalHeight); m_bottomOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + outlineGeometry.height() - 5, horizontalWidth, horizontalHeight); const xcb_render_color_t white = {0xffff, 0xffff, 0xffff, 0xffff}; QColor qGray(Qt::gray); const xcb_render_color_t gray = { uint16_t(0xffff * qGray.redF()), uint16_t(0xffff * qGray.greenF()), uint16_t(0xffff * qGray.blueF()), 0xffff }; const xcb_render_color_t black = {0, 0, 0, 0xffff}; { xcb_pixmap_t xpix = xcb_generate_id(connection()); xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), verticalWidth, verticalHeight); XRenderPicture pic(xpix, defaultDepth); xcb_rectangle_t rect = {0, 0, 5, verticalHeight}; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); rect.x = 1; rect.width = 3; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 1, &rect); rect.x = 2; rect.width = 1; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 1, &rect); m_leftOutline.setBackgroundPixmap(xpix); m_rightOutline.setBackgroundPixmap(xpix); // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. xcb_free_pixmap(connection(), xpix); } { xcb_pixmap_t xpix = xcb_generate_id(connection()); xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), horizontalWidth, horizontalHeight); XRenderPicture pic(xpix, defaultDepth); xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight}; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); xcb_rectangle_t grayRects[] = { {1, 1, uint16_t(horizontalWidth -2), 3}, {1, 4, 3, 1}, {int16_t(horizontalWidth - 4), 4, 3, 1} }; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects); xcb_rectangle_t blackRects[] = { {2, 2, uint16_t(horizontalWidth -4), 1}, {2, 3, 1, 2}, {int16_t(horizontalWidth - 3), 3, 1, 2} }; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects); m_topOutline.setBackgroundPixmap(xpix); // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. xcb_free_pixmap(connection(), xpix); } { xcb_pixmap_t xpix = xcb_generate_id(connection()); xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), outlineGeometry.width(), 5); XRenderPicture pic(xpix, defaultDepth); xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight}; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); xcb_rectangle_t grayRects[] = { {1, 1, uint16_t(horizontalWidth -2), 3}, {1, 0, 3, 1}, {int16_t(horizontalWidth - 4), 0, 3, 1} }; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects); xcb_rectangle_t blackRects[] = { {2, 2, uint16_t(horizontalWidth -4), 1}, {2, 0, 1, 2}, {int16_t(horizontalWidth - 3), 0, 1, 2} }; xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects); m_bottomOutline.setBackgroundPixmap(xpix); // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. xcb_free_pixmap(connection(), xpix); } forEachWindow(&Xcb::Window::clear); forEachWindow(&Xcb::Window::map); }