📄 matchbox-keyboard-ui.c
字号:
if (streq(wm_name, "matchbox")) have_matchbox_wm = True; } win_attr.override_redirect = False; /* Set to true for extreme case */ win_attr.event_mask = ButtonPressMask|ButtonReleaseMask|Button1MotionMask|StructureNotifyMask; ui->xwin = XCreateWindow(ui->xdpy, ui->xwin_root, 0, 0, ui->xwin_width, ui->xwin_height, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect|CWEventMask, &win_attr); wm_hints = XAllocWMHints(); if (wm_hints) { DBG("setting no focus hint"); wm_hints->input = False; wm_hints->flags = InputHint; XSetWMHints(ui->xdpy, ui->xwin, wm_hints ); XFree(wm_hints); } size_hints.flags = PPosition | PSize | PMinSize; size_hints.x = 0; size_hints.y = 0; size_hints.width = ui->xwin_width; size_hints.height = ui->xwin_height; size_hints.min_width = ui->xwin_width; size_hints.min_height = ui->xwin_height; XSetStandardProperties(ui->xdpy, ui->xwin, "Keyboard", NULL, 0, NULL, 0, &size_hints); if (!ui->want_embedding) { mwm_hints = util_malloc0(sizeof(PropMotifWmHints)); if (mwm_hints) { mwm_hints->flags = MWM_HINTS_DECORATIONS; mwm_hints->decorations = 0; XChangeProperty(ui->xdpy, ui->xwin, atom_MOTIF_WM_HINTS, XA_ATOM, 32, PropModeReplace, (unsigned char *)mwm_hints, PROP_MOTIF_WM_HINTS_ELEMENTS); free(mwm_hints); } if (have_ewmh_wm) { /* XXX Fix this for display size */ int wm_struct_vals[] = { 0, /* left */ 0, /* right */ 0, /* top */ 0, /* bottom */ 0, /* left_start_y */ 0, /* left_end_y */ 0, /* right_start_y */ 0, /* right_end_y */ 0, /* top_start_x */ 0, /* top_end_x */ 0, /* bottom_start_x */ 1399 }; /* bottom_end_x */ Atom states[] = { atom_NET_WM_STATE_SKIP_TASKBAR, atom_NET_WM_STATE_SKIP_PAGER }; int desk_width = 0, desk_height = 0, desk_y = 0; XChangeProperty(ui->xdpy, ui->xwin, atom_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)states, 2); if (get_desktop_area(ui, NULL, &desk_y, &desk_width, &desk_height)) { /* Assuming we take up all available display width * ( at least true with matchbox wm ). we resize * the base ui width to this ( and height as a factor ) * to avoid the case of mapping and then the wm resizing * us, causing an ugly repaint. */ if (desk_width > ui->xwin_width) { mb_kbd_ui_resize(ui, desk_width, ( desk_width * ui->xwin_height ) / ui->xwin_width); } wm_struct_vals[2] = desk_y + desk_height - ui->xwin_height; wm_struct_vals[11] = desk_width; XChangeProperty(ui->xdpy, ui->xwin, atom_NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)wm_struct_vals , 12); DBG("desk width: %i, desk height: %i xwin_height :%i", desk_width, desk_height, ui->xwin_height); } if (have_matchbox_wm) { XChangeProperty(ui->xdpy, ui->xwin, atom_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &atom_NET_WM_WINDOW_TYPE_TOOLBAR, 1); } else { /* XChangeProperty(ui->xdpy, ui->xwin, atom_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &atom_NET_WM_WINDOW_TYPE_DOCK, 1); */ } } } ui->backbuffer = XCreatePixmap(ui->xdpy, ui->xwin, ui->xwin_width, ui->xwin_height, DefaultDepth(ui->xdpy, ui->xscreen)); XSetWindowBackgroundPixmap(ui->xdpy, ui->xwin, ui->backbuffer); ui->backend->resources_create(ui); /* Get root size change events for rotation */ /* XSelectInput(ui->xdpy, ui->xwin_root, StructureNotifyMask); */ return 1;}static voidmb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) { MBKeyboard *kbd = ui->kbd; MBKeyboardLayout *layout; List *row_item, *key_item; int width_diff, height_diff; int height_font_pt_size, width_font_pt_size; int next_row_y, n_rows, extra_key_height; MARK(); width_diff = width - ui->base_alloc_width; height_diff = height - ui->base_alloc_height; if (width_diff < 0 || height_diff < 0) return; /* dont go smaller than our int request - get clipped */ layout = mb_kbd_get_selected_layout(ui->kbd); row_item = mb_kbd_layout_rows(layout); /* load a bigger font ? * Only load if height and width have changed */ width_font_pt_size = ( (ui->base_font_pt_size * width) / ui->base_alloc_width ); if (util_abs(width_font_pt_size - kbd->font_pt_size) > 2) { height_font_pt_size = ( (ui->base_font_pt_size * height) / ui->base_alloc_height ); if (util_abs(height_font_pt_size - kbd->font_pt_size) > 2) { ui->kbd->font_pt_size = (height_font_pt_size > width_font_pt_size) ? width_font_pt_size : height_font_pt_size; mb_kbd_ui_load_font(ui); } } n_rows = util_list_length(row_item); extra_key_height = (height_diff / n_rows); DBG("****** extra height is %i ******", extra_key_height); next_row_y = mb_kbd_row_spacing(ui->kbd); /* allocate the extra width we have as padding to keys */ while (row_item != NULL) { int row_base_width, new_row_base_width, row_width_diff; int next_key_x = 0, n_fillers = 0, free_space = 0, new_w = 0; row_base_width = mb_kbd_row_base_width(row_item->data); new_row_base_width = ( row_base_width * width ) / ui->base_alloc_width; row_width_diff = new_row_base_width - row_base_width; DBG("row_width_diff = %i", row_width_diff); next_key_x = mb_kbd_col_spacing(ui->kbd); /* * row_base_width * -------------- X new_width = new_base_width * base_width * * key_extra_pad = key_base_width X base_width_diff * -------------------------------- * row_base_width */ mb_kbd_row_for_each_key(row_item->data, key_item) { MBKeyboardKey *key = key_item->data; int key_base_width, key_new_pad; if (!mb_kbd_is_extended(kbd) && mb_kbd_key_get_extended(key)) continue; key_base_width =( mb_kbd_key_width(key) - mb_kbd_key_get_extra_width_pad(key)); key_new_pad= ( (key_base_width + mb_kbd_col_spacing(kbd)) * row_width_diff) / row_base_width; mb_kbd_key_set_extra_width_pad (key, key_new_pad ); /* Height */ mb_kbd_key_set_extra_height_pad (key, extra_key_height); mb_kbd_key_set_geometry(key, next_key_x, -1, -1, -1); next_key_x += (mb_kbd_key_width(key) + mb_kbd_col_spacing(ui->kbd)); if (mb_kbd_key_get_fill(key)) n_fillers++; } /* The above ( likely due to rounding ) leaves a few pixels free. * This can be critical on a small handheld display. Therefore * we do a second parse deviding up any left over space between * keys marked as fill. */ if (n_fillers) { free_space = width - mb_kbd_row_width(row_item->data); mb_kbd_row_for_each_key(row_item->data, key_item) { if (!mb_kbd_is_extended(kbd) && mb_kbd_key_get_extended(key_item->data)) continue; if (mb_kbd_key_get_fill(key_item->data)) { int old_w; List *nudge_key_item = util_list_next(key_item); old_w = mb_kbd_key_width(key_item->data); new_w = old_w + (free_space/n_fillers); mb_kbd_key_set_geometry(key_item->data, -1, -1, new_w, -1); /* nudge next keys forward */ for (; nudge_key_item != NULL; nudge_key_item = util_list_next(nudge_key_item)) { if (!mb_kbd_is_extended(ui->kbd) && mb_kbd_key_get_extended(nudge_key_item->data)) continue; mb_kbd_key_set_geometry(nudge_key_item->data, mb_kbd_key_x(nudge_key_item->data) + (new_w - old_w ), -1, -1, -1); } } } } /* re-center row */ mb_kbd_row_set_x(row_item->data, (width - mb_kbd_row_width(row_item->data))/2); /* and position down */ mb_kbd_row_set_y(row_item->data, next_row_y); next_row_y += (mb_kbd_row_height(row_item->data) + mb_kbd_row_spacing(ui->kbd)); row_item = util_list_next(row_item); } /* center entire layout vertically if space left */ if (next_row_y < height) { int vspace = ( height - next_row_y ) / 2; row_item = mb_kbd_layout_rows(layout); while (row_item != NULL) { mb_kbd_row_set_y(row_item->data, mb_kbd_row_y(row_item->data) + vspace + 1); row_item = util_list_next(row_item); } } XResizeWindow(ui->xdpy, ui->xwin, width, height); ui->xwin_width = width; ui->xwin_height = height; if (ui->backbuffer) /* may get called before initialised */ { XFreePixmap(ui->xdpy, ui->backbuffer); ui->backbuffer = XCreatePixmap(ui->xdpy, ui->xwin, ui->xwin_width, ui->xwin_height, DefaultDepth(ui->xdpy, ui->xscreen)); ui->backend->resize(ui, width, height); XSetWindowBackgroundPixmap(ui->xdpy, ui->xwin, ui->backbuffer); mb_kbd_ui_redraw(ui); }}voidmb_kbd_ui_handle_configure(MBKeyboardUI *ui, int width, int height){ boolean old_state, new_state; MARK(); /* Figure out if screen size has changed - does a round trip - bad */ update_display_size(ui); old_state = mb_kbd_is_extended(ui->kbd); new_state = want_extended(ui); if (new_state == old_state) /* Not a rotation */ { mb_kbd_ui_resize(ui, width, height); return; } mb_kbd_set_extended(ui->kbd, new_state); /* realocate the layout */ mb_kbd_ui_allocate_ui_layout(ui, &ui->base_alloc_width, &ui->base_alloc_height); mb_kbd_ui_resize(ui, width, height); }voidmb_kbd_ui_event_loop(MBKeyboardUI *ui){ MBKeyboardKey *key = NULL; struct timeval tvt; /* Key repeat - values for standard xorg install ( xset q) */ int repeat_delay = 100 * 10000; int repeat_rate = 30 * 1000; tvt.tv_sec = 0; tvt.tv_usec = repeat_delay; while (True) { XEvent xev; if (get_xevent_timed(ui->xdpy, &xev, &tvt)) { switch (xev.type) { case ButtonPress: DBG("got button bress at %i,%i", xev.xbutton.x, xev.xbutton.y); key = mb_kbd_locate_key(ui->kbd, xev.xbutton.x, xev.xbutton.y); if (key) { /* Hack if we never get a release event */ if (key != mb_kbd_get_held_key(ui->kbd)) { mb_kbd_key_release(ui->kbd); tvt.tv_usec = repeat_delay; } else tvt.tv_usec = repeat_rate; DBG("found key for press"); mb_kbd_key_press(key); } break; case ButtonRelease: if (mb_kbd_get_held_key(ui->kbd) != NULL) { mb_kbd_key_release(ui->kbd); tvt.tv_usec = repeat_delay; } break; case ConfigureNotify: if (xev.xconfigure.width != ui->xwin_width || xev.xconfigure.height != ui->xwin_height) mb_kbd_ui_handle_configure(ui, xev.xconfigure.width, xev.xconfigure.height); break; case MappingNotify: fakekey_reload_keysyms(ui->fakekey); XRefreshKeyboardMapping(&xev.xmapping); break; default: break; } if (ui->want_embedding) mb_kbd_xembed_process_xevents (ui, &xev); } else { /* Keyrepeat */ if (mb_kbd_get_held_key(ui->kbd) != NULL) { fakekey_repeat(ui->fakekey); tvt.tv_usec = repeat_rate; } } }}static intmb_kbd_ui_load_font(MBKeyboardUI *ui){ return ui->backend->font_load(ui);}intmb_kbd_ui_display_width(MBKeyboardUI *ui){ return ui->dpy_width;}intmb_kbd_ui_display_height(MBKeyboardUI *ui){ return ui->dpy_height;}MBKeyboardUIBackend*mb_kbd_ui_backend(MBKeyboardUI *ui){ return ui->backend;}Display*mb_kbd_ui_x_display(MBKeyboardUI *ui){ return ui->xdpy;}intmb_kbd_ui_x_screen(MBKeyboardUI *ui){ return ui->xscreen;}Windowmb_kbd_ui_x_win(MBKeyboardUI *ui){ return ui->xwin;}Windowmb_kbd_ui_x_win_root(MBKeyboardUI *ui){ return ui->xwin_root;}intmb_kbd_ui_x_win_height(MBKeyboardUI *ui){ return ui->xwin_height;}intmb_kbd_ui_x_win_width(MBKeyboardUI *ui){ return ui->xwin_width;}Pixmapmb_kbd_ui_backbuffer(MBKeyboardUI *ui){ return ui->backbuffer;}MBKeyboard*mb_kbd_ui_kbd(MBKeyboardUI *ui){ return ui->kbd;}intmb_kbd_ui_realize(MBKeyboardUI *ui){ ui->base_font_pt_size = ui->kbd->font_pt_size; if (!mb_kbd_ui_load_font(ui)) return 0; /* potrait or landscape */ if (want_extended(ui)) mb_kbd_set_extended(ui->kbd, True); /* * figure out how small this keyboard can be.. */ mb_kbd_ui_allocate_ui_layout(ui, &ui->base_alloc_width, &ui->base_alloc_height); ui->xwin_width = ui->base_alloc_width; ui->xwin_height = ui->base_alloc_height; mb_kbd_ui_resources_create(ui); unless (mb_kbd_ui_embeded(ui)) { mb_kbd_ui_show(ui); mb_kbd_ui_redraw(ui); } else mb_kbd_xembed_init (ui); return 1;}intmb_kbd_ui_init(MBKeyboard *kbd){ MBKeyboardUI *ui = NULL; ui = kbd->ui = util_malloc0(sizeof(MBKeyboardUI)); ui->kbd = kbd; if ((ui->xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) return 0; if ((ui->fakekey = fakekey_init(ui->xdpy)) == NULL) return 0; ui->xscreen = DefaultScreen(ui->xdpy); ui->xwin_root = RootWindow(ui->xdpy, ui->xscreen); ui->backend = MB_KBD_UI_BACKEND_INIT_FUNC(ui); update_display_size(ui); return 1;}/* Embedding */voidmb_kbd_ui_set_embeded (MBKeyboardUI *ui, int embed){ ui->want_embedding = embed;} intmb_kbd_ui_embeded (MBKeyboardUI *ui){ return ui->want_embedding;}voidmb_kbd_ui_print_window (MBKeyboardUI *ui){ fprintf(stdout, "%li\n", mb_kbd_ui_x_win(ui)); fflush(stdout);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -