⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matchbox-keyboard-ui.c

📁 Linux系统上的一款屏幕软键盘
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *  Matchbox Keyboard - A lightweight software keyboard. * *  Authored By Matthew Allum <mallum@o-hand.com> * *  Copyright (c) 2005 OpenedHand Ltd - http://o-hand.com * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * */#include "matchbox-keyboard.h"#define PROP_MOTIF_WM_HINTS_ELEMENTS    5#define MWM_HINTS_DECORATIONS          (1L << 1)#define MWM_DECOR_BORDER               (1L << 1)typedef struct{  unsigned long       flags;  unsigned long       functions;  unsigned long       decorations;  long                inputMode;  unsigned long       status;} PropMotifWmHints;struct MBKeyboardUI{  Display            *xdpy;  int                 xscreen;  Window              xwin_root, xwin;  Pixmap              backbuffer;  int                 dpy_width, dpy_height;  int                 xwin_width, xwin_height;  int                 key_uwidth, key_uheight;  int                 base_alloc_width, base_alloc_height;  int                 base_font_pt_size;  Bool                want_embedding;  FakeKey             *fakekey;  MBKeyboardUIBackend *backend;   MBKeyboard          *kbd;};static voidmb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height);static intmb_kbd_ui_load_font(MBKeyboardUI *ui);static char*get_current_window_manager_name (MBKeyboardUI  *ui){  Atom           atom_utf8_string, atom_wm_name, atom_check, type;  int            result, format;  char          *val, *retval;  unsigned long  nitems, bytes_after;  Window        *support_xwin = NULL;  atom_check = XInternAtom (ui->xdpy, "_NET_SUPPORTING_WM_CHECK", False);  XGetWindowProperty (ui->xdpy, 		      RootWindow(ui->xdpy, ui->xscreen),		      atom_check,		      0, 16L, False, XA_WINDOW, &type, &format,		      &nitems, &bytes_after, (unsigned char **)&support_xwin);  if (support_xwin == NULL)      return NULL;  atom_utf8_string = XInternAtom (ui->xdpy, "UTF8_STRING", False);  atom_wm_name     = XInternAtom (ui->xdpy, "_NET_WM_NAME", False);  result = XGetWindowProperty (ui->xdpy, *support_xwin, atom_wm_name,			       0, 1000L,False, atom_utf8_string,			       &type, &format, &nitems,			       &bytes_after, (unsigned char **)&val);  if (result != Success)    return NULL;  if (type != atom_utf8_string || format !=8 || nitems == 0)    {      if (val) XFree (val);      return NULL;    }  retval = strdup (val);  XFree (val);  return retval;}static booleanget_desktop_area(MBKeyboardUI *ui, int *x, int *y, int *width, int *height){  Atom           atom_area, type;  int            result, format;  unsigned long  nitems, bytes_after;  int           *geometry = NULL;  atom_area = XInternAtom (ui->xdpy, "_NET_WORKAREA", False);  result = XGetWindowProperty (ui->xdpy, 			       RootWindow(ui->xdpy, ui->xscreen),			       atom_area,			       0, 16L, False, XA_CARDINAL, &type, &format,			       &nitems, &bytes_after, 			       (unsigned char **)&geometry);  if (result != Success || nitems < 4 || geometry == NULL)    {      if (geometry) XFree(geometry);      return False;    }  if (x) *x           = geometry[0];  if (y) *y           = geometry[1];  if (width)  *width  = geometry[2];  if (height) *height = geometry[3];    XFree(geometry);  return True;}static voidupdate_display_size(MBKeyboardUI *ui){  XWindowAttributes winattr;  XGetWindowAttributes(ui->xdpy, ui->xwin_root, &winattr);  /* XXX should actually trap an X error here */  ui->dpy_width  = winattr.width;  ui->dpy_height = winattr.height;  return;}static booleanwant_extended(MBKeyboardUI *ui){  /* Are we in portrait ? */  if (ui->dpy_width > ui->dpy_height)    return True;  return False;}static booleanget_xevent_timed(Display        *dpy,		 XEvent         *event_return, 		 struct timeval *tv){  if (tv->tv_usec == 0 && tv->tv_sec == 0)    {      XNextEvent(dpy, event_return);      return True;    }  XFlush(dpy);  if (XPending(dpy) == 0)     {      int fd = ConnectionNumber(dpy);      fd_set readset;      FD_ZERO(&readset);      FD_SET(fd, &readset);      if (select(fd+1, &readset, NULL, NULL, tv) == 0) 	return False;      else 	{	  XNextEvent(dpy, event_return);	  return True;	}    } else {      XNextEvent(dpy, event_return);      return True;    }}voidmb_kbd_ui_send_press(MBKeyboardUI        *ui,		     const char          *utf8_char_in,		     int                  modifiers){  DBG("Sending '%s'", utf8_char_in);  fakekey_press(ui->fakekey, (unsigned char*)utf8_char_in, -1, modifiers);}voidmb_kbd_ui_send_keysym_press(MBKeyboardUI  *ui,			    KeySym         ks,			    int            modifiers){  fakekey_press_keysym(ui->fakekey, ks, modifiers);}voidmb_kbd_ui_send_release(MBKeyboardUI  *ui){  fakekey_release(ui->fakekey);}static voidmb_kdb_ui_unit_key_size(MBKeyboardUI *ui, int *width, int *height){  MBKeyboardLayout       *layout;  List                   *row_item, *key_item;  MBKeyboardKeyStateType  state;  const char             *face_str;  *width = 0; *height = 0;  layout   = mb_kbd_get_selected_layout(ui->kbd);  row_item = mb_kbd_layout_rows(layout);  /*   * Figure out the base size of a 'regular' single glyph key.      */  while (row_item != NULL)    {      mb_kbd_row_for_each_key(row_item->data, key_item)	{	  MBKeyboardKey *key = key_item->data;	  if (!mb_kbd_is_extended(ui->kbd) 	      && mb_kbd_key_get_extended(key))	    continue;	  mb_kdb_key_foreach_state(key, state)	    {	      if (mb_kbd_key_get_face_type(key, state) == MBKeyboardKeyFaceGlyph)		{		  face_str = mb_kbd_key_get_glyph_face(key, state);		  if (util_utf8_char_cnt(face_str) == 1)		    {		      int str_w =0, str_h = 0;		      ui->backend->text_extents(ui, face_str, &str_w, &str_h);		      		      if (str_w > *width) *width = str_w;		      if (str_h > *height) *height = str_h;		    }		}	      /* TODO: also need to check height of image keys etc */	    }	}      row_item = util_list_next(row_item);    }  /* FIXME: hack for small displays */  if (mb_kbd_ui_display_height(ui) <= 320)    {      *height += 4;    }}static voidmb_kbd_ui_min_key_size(MBKeyboardUI  *ui,		       MBKeyboardKey *key,		       int           *width,		       int           *height){  const char *face_str = NULL;  int         max_w = 0, max_h = 0, state;  /*    * Figure out how small a key can really be UI wise.  */  if (mb_kbd_key_get_req_uwidth(key) || mb_kbd_key_is_blank(key))    {      *width = (ui->key_uwidth * mb_kbd_key_get_req_uwidth(key)) / 1000 ;      *height = ui->key_uheight;      return;    }  mb_kdb_key_foreach_state(key, state)    {      if (mb_kbd_key_get_face_type(key, state) == MBKeyboardKeyFaceGlyph)	{	  face_str = mb_kbd_key_get_glyph_face(key, state);	  ui->backend->text_extents(ui, face_str, width, height);	  if (*width < max_w) *width = max_w;	  if (*height < max_h) *height = max_h;	}      /* XXX else, images etc */    }}voidmb_kbd_ui_allocate_ui_layout(MBKeyboardUI *ui,			     int          *width,			     int          *height){  MBKeyboardLayout *layout;  List             *row_item, *key_item;  int               key_y = 0, key_x = 0;   int               row_y, max_row_key_height, max_row_width;  layout = mb_kbd_get_selected_layout(ui->kbd);  /* Do an initial run to figure out a 'base' size for single glyph keys */  mb_kdb_ui_unit_key_size(ui, &ui->key_uwidth, &ui->key_uheight);  row_item = mb_kbd_layout_rows(layout);  row_y = mb_kbd_row_spacing(ui->kbd);   max_row_width = 0;  /*    * First of entire keyboard, basically get the minimum space needed  */  while (row_item != NULL)    {      MBKeyboardRow *row = row_item->data;            key_x = mb_kbd_col_spacing(ui->kbd);      max_row_key_height = 0;      mb_kbd_row_for_each_key(row, key_item)	{	  int            key_w, key_h;          	  MBKeyboardKey *key = key_item->data;	  mb_kbd_key_set_extra_height_pad(key, 0);	  mb_kbd_key_set_extra_width_pad(key, 0);	  mb_kbd_key_set_geometry(key, 0, 0, 0, 0);	  if (!mb_kbd_is_extended(ui->kbd) && mb_kbd_key_get_extended(key))	    continue;	  mb_kbd_ui_min_key_size(ui, key, &key_w, &key_h);	  if (!mb_kbd_key_get_req_uwidth(key)	      && key_w < ui->key_uwidth)	    key_w = ui->key_uwidth;	  if (key_h < ui->key_uheight) 	    key_h = ui->key_uheight;	  key_y = 0;	  key_w += 2 * ( mb_kbd_keys_border(ui->kbd) 			 + mb_kbd_keys_margin(ui->kbd) 			 + mb_kbd_keys_pad(ui->kbd) );	  key_h += 2 * ( mb_kbd_keys_border(ui->kbd) 			 + mb_kbd_keys_margin(ui->kbd) 			 + mb_kbd_keys_pad(ui->kbd) );	  	  if (key_h > max_row_key_height)	    max_row_key_height = key_h;	  mb_kbd_key_set_geometry(key, key_x, key_y, key_w, key_h); 	  	  key_x += (mb_kbd_col_spacing(ui->kbd) + key_w);	}      if (key_x > max_row_width) /* key_x now represents row width */	max_row_width = key_x;      mb_kbd_row_set_y(row, row_y);      row_y += max_row_key_height + mb_kbd_row_spacing(ui->kbd);      row_item = util_list_next(row_item);    }  *height = row_y;   row_item = mb_kbd_layout_rows(layout);  /* Now pass again allocating any extra space with have left over */  while (row_item != NULL)    {      MBKeyboardRow *row        = row_item->data;      int            n_fillers  = 0, free_space = 0, new_w = 0;      mb_kbd_row_for_each_key(row,key_item)	{	  if (!mb_kbd_is_extended(ui->kbd) 	      && mb_kbd_key_get_extended(key_item->data))	    continue;	  if (mb_kbd_key_get_fill(key_item->data)	      || mb_kbd_ui_display_height(ui) <= 320	      || mb_kbd_ui_display_width(ui) <= 320 )	      n_fillers++;	}      if (!n_fillers)	goto next_row;      free_space = max_row_width - mb_kbd_row_width(row);      mb_kbd_row_for_each_key(row, key_item)	{	  if (!mb_kbd_is_extended(ui->kbd) 	      && mb_kbd_key_get_extended(key_item->data))	    continue;	  if (mb_kbd_key_get_fill(key_item->data)	      || mb_kbd_ui_display_height(ui) <= 320	      || mb_kbd_ui_display_width(ui) <= 320 )	    {	      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);		  		}	    }	}    next_row:      row_item = util_list_next(row_item);    }  /* Now center the rows */    row_item = mb_kbd_layout_rows(layout);  while (row_item != NULL)    {      MBKeyboardRow *row = row_item->data;      mb_kbd_row_set_x(row, (max_row_width - mb_kbd_row_width(row))/2);      row_item = util_list_next(row_item);    }    *width = max_row_width;}voidmb_kbd_ui_redraw_key(MBKeyboardUI  *ui, MBKeyboardKey *key){  ui->backend->redraw_key(ui, key);}static voidmb_kbd_ui_redraw_row(MBKeyboardUI  *ui, MBKeyboardRow *row){  List *key_item;  mb_kbd_row_for_each_key(row, key_item)    {      if (!mb_kbd_is_extended(ui->kbd) 	  && mb_kbd_key_get_extended(key_item->data))	continue;      mb_kbd_ui_redraw_key(ui, key_item->data);    }}voidmb_kbd_ui_swap_buffers(MBKeyboardUI  *ui){  XClearWindow(ui->xdpy, ui->xwin);  XSync(ui->xdpy, False);}voidmb_kbd_ui_redraw(MBKeyboardUI  *ui){  List             *row_item;  MBKeyboardLayout *layout;  MARK();  /* gives backend a chance to clear everything */  ui->backend->pre_redraw(ui);  layout = mb_kbd_get_selected_layout(ui->kbd);  row_item = mb_kbd_layout_rows(layout);  while (row_item != NULL)    {      MBKeyboardRow *row = row_item->data;      mb_kbd_ui_redraw_row(ui, row);      row_item = util_list_next(row_item);    }  mb_kbd_ui_swap_buffers(ui);}voidmb_kbd_ui_show(MBKeyboardUI  *ui){  XMapWindow(ui->xdpy, ui->xwin);}			  static intmb_kbd_ui_resources_create(MBKeyboardUI  *ui){#define PROP_MOTIF_WM_HINTS_ELEMENTS    5#define MWM_HINTS_DECORATIONS          (1L << 1)#define MWM_DECOR_BORDER               (1L << 1)  typedef struct  {    unsigned long       flags;    unsigned long       functions;    unsigned long       decorations;    long                inputMode;    unsigned long       status;  } PropMotifWmHints ;  Atom /* atom_wm_protocols[3], */      atom_NET_WM_WINDOW_TYPE,      atom_NET_WM_WINDOW_TYPE_TOOLBAR,     atom_NET_WM_WINDOW_TYPE_DOCK,     atom_NET_WM_STRUT_PARTIAL,     atom_NET_WM_STATE_SKIP_PAGER,     atom_NET_WM_STATE_SKIP_TASKBAR,     atom_NET_WM_STATE,     atom_MOTIF_WM_HINTS;    PropMotifWmHints    *mwm_hints;  XSizeHints           size_hints;  XWMHints            *wm_hints;  XSetWindowAttributes win_attr;  char                *wm_name;  boolean              have_matchbox_wm = False;               boolean              have_ewmh_wm     = False;               /*  atom_wm_protocols = {     XInternAtom(ui->xdpy, "WM_DELETE_WINDOW",False),    XInternAtom(ui->xdpy, "WM_PROTOCOLS",False),    XInternAtom(ui->xdpy, "WM_NORMAL_HINTS", False),  };  */  atom_NET_WM_WINDOW_TYPE =    XInternAtom(ui->xdpy, "_NET_WM_WINDOW_TYPE" , False);  atom_NET_WM_WINDOW_TYPE_TOOLBAR =    XInternAtom(ui->xdpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);  atom_NET_WM_WINDOW_TYPE_DOCK =     XInternAtom(ui->xdpy, "_NET_WM_WINDOW_TYPE_DOCK", False);  atom_MOTIF_WM_HINTS =    XInternAtom(ui->xdpy, "_MOTIF_WM_HINTS", False);  atom_NET_WM_STRUT_PARTIAL =     XInternAtom(ui->xdpy, "_NET_WM_STRUT_PARTIAL", False);  atom_NET_WM_STATE_SKIP_TASKBAR =    XInternAtom(ui->xdpy, "_NET_WM_STATE_SKIP_TASKBAR", False);  atom_NET_WM_STATE_SKIP_PAGER =     XInternAtom(ui->xdpy, "_NET_WM_STATE_SKIP_PAGER", False);  atom_NET_WM_STATE =    XInternAtom(ui->xdpy, "_NET_WM_STATE", False);  if ((wm_name = get_current_window_manager_name(ui)) != NULL)    {      have_ewmh_wm = True; 	/* basically assumed to be Metacity				   or at least only tested with mcity */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -