diff options
author | Koen Kooi <koen@openembedded.org> | 2006-11-11 13:16:58 +0000 |
---|---|---|
committer | Koen Kooi <koen@openembedded.org> | 2006-11-11 13:16:58 +0000 |
commit | c43741cf643c1842b0f40821b7d8d745e5d697b6 (patch) | |
tree | dd30261a658bcd0e93e88f106fa63026e8ae7e64 /packages/matchbox-applet-inputmanager/files | |
parent | 6e038183866f6c77acf971e5c83a9cf967b26f40 (diff) |
mb-applet-inputmanager: apply patch from Phil Blundell to pop up input method on focus
* requires libgtkinput to be loaded
* see http://www.nabble.com/libgtkinput-t971843.html
* this also brings mbinputmgr-tray.c in sync with o-hand svn rev 1163
Diffstat (limited to 'packages/matchbox-applet-inputmanager/files')
4 files changed, 798 insertions, 0 deletions
diff --git a/packages/matchbox-applet-inputmanager/files/.mtn2git_empty b/packages/matchbox-applet-inputmanager/files/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/matchbox-applet-inputmanager/files/.mtn2git_empty diff --git a/packages/matchbox-applet-inputmanager/files/mbinputmgr-libgtkinput.patch b/packages/matchbox-applet-inputmanager/files/mbinputmgr-libgtkinput.patch new file mode 100644 index 0000000000..5d1ccdc0c7 --- /dev/null +++ b/packages/matchbox-applet-inputmanager/files/mbinputmgr-libgtkinput.patch @@ -0,0 +1,350 @@ +Index: mb-applet-input-manager-0.6/mbinputmgr-tray.c +=================================================================== +--- mb-applet-input-manager-0.6/mbinputmgr-tray.c (revision 1292) ++++ mb-applet-input-manager-0.6/mbinputmgr-tray.c (working copy) +@@ -32,8 +32,20 @@ + MBInpmgrState *Inpmgr_state = NULL; + Bool ButtonIsDown = False; + int ButtonActive; +-Atom AtomIMActivate; + ++Atom atoms[2]; ++char *atom_names[] = ++ { ++ "_MB_INPUT_REQUEST", ++ "_GPE_INPUT_MANAGER" ++ }; ++ ++#define _MB_INPUT_REQUEST 0 ++#define _GPE_INPUT_MANAGER 1 ++ ++#define _GPE_INPUT_MANAGER_OPEN 1 ++#define _GPE_INPUT_MANAGER_CLOSE 2 ++ + typedef struct ButtonImgs { + + MBPixbufImage *active; +@@ -41,6 +53,17 @@ + + } ButtonImgs; + ++struct window_record ++{ ++ Window w; ++ struct window_record *next; ++}; ++ ++struct window_record *requests; ++ ++Display *dpy; ++Bool auto_enabled; ++ + void + paint_callback ( MBTrayApp *app, Drawable drw ) + { +@@ -262,14 +285,190 @@ + } + + void ++really_close (void) ++{ ++ if (requests == NULL && mbinputmgr_method_active (Inpmgr_state) && auto_enabled) ++ { ++ mbinputmgr_toggle_selected_method (Inpmgr_state); ++ auto_enabled = False; ++ } ++} ++ ++Bool timer_active; ++struct timeval expires; ++ ++Bool ++get_timeout (struct timeval *tv) ++{ ++ int sec, usec; ++ struct timeval now; ++ ++ if (!timer_active) ++ return False; ++ ++ gettimeofday (&now, NULL); ++ ++ sec = expires.tv_sec - now.tv_sec; ++ usec = expires.tv_usec - now.tv_usec; ++ if (usec < 0) ++ { ++ sec--; ++ usec += 1000000; ++ } ++ ++ if (sec < 0) ++ { ++ /* timer expired */ ++ really_close (); ++ timer_active = False; ++ return False; ++ } ++ ++ tv->tv_sec = sec; ++ tv->tv_usec = usec; ++ ++ return True; ++} ++ ++Bool ++process_close_request (Window w) ++{ ++ struct window_record *r, *pr = NULL; ++ unsigned long tv; ++ ++ for (r = requests; r != NULL && r->w != w; ) ++ { ++ pr = r; ++ r = r->next; ++ } ++ ++ if (r) ++ { ++ if (pr) ++ pr->next = r->next; ++ else ++ requests = r->next; ++ ++ free (r); ++ ++ if (requests == NULL && mbinputmgr_method_active (Inpmgr_state) && auto_enabled) ++ { ++ timer_active = True; ++ gettimeofday (&expires, NULL); ++ expires.tv_usec += 100000; ++ if (expires.tv_usec >= 1000000) ++ { ++ expires.tv_sec++; ++ expires.tv_usec -= 1000000; ++ } ++ } ++ ++ return True; ++ } ++ ++ return False; ++} ++ ++int trapped_error_code; ++int (*old_error_handler) (Display *d, XErrorEvent *e); ++ ++static int ++error_handler(Display *display, ++ XErrorEvent *error) ++{ ++ trapped_error_code = error->error_code; ++ return 0; ++} ++ ++static void ++trap_errors(void) ++{ ++ trapped_error_code = 0; ++ old_error_handler = XSetErrorHandler(error_handler); ++} ++ ++static int ++untrap_errors(void) ++{ ++ XSetErrorHandler(old_error_handler); ++ return trapped_error_code; ++} ++ ++Bool ++process_open_request (Window w) ++{ ++ struct window_record *r; ++ ++ for (r = requests; r != NULL && r->w != w; r = r->next) ++ ; ++ ++ if (r) ++ return True; ++ ++ trap_errors (); ++ XSelectInput (dpy, w, StructureNotifyMask); ++ XSync (dpy, False); ++ if (untrap_errors ()) ++ return False; ++ ++ r = malloc (sizeof (*r)); ++ r->next = requests; ++ r->w = w; ++ requests = r; ++ ++ if (!mbinputmgr_method_active(Inpmgr_state)) ++ { ++ mbinputmgr_toggle_selected_method (Inpmgr_state); ++ auto_enabled = True; ++ } ++ ++ return False; ++} ++ ++Bool docked_already; ++ ++void ++is_docked (void) ++{ ++ Window tray_w; ++ ++ tray_w = mb_tray_app_xwin (app); ++ ++ if (XGetSelectionOwner (dpy, atoms[_GPE_INPUT_MANAGER]) == None) ++ { ++ XSetSelectionOwner (dpy, atoms[_GPE_INPUT_MANAGER], tray_w, CurrentTime); ++ } ++ else ++ { ++ fprintf (stderr, "Unable to claim _GPE_INPUT_MANAGER selection.\n"); ++ } ++} ++ ++void + xevent_callback (MBTrayApp *app, XEvent *ev) + { + if (ev->type == ClientMessage) + { + XClientMessageEvent *cmev = (XClientMessageEvent *)&ev->xconfigure; + +- if (cmev->message_type == AtomIMActivate) ++ if (cmev->message_type == atoms[_GPE_INPUT_MANAGER]) + { ++ switch (cmev->data.l[0]) ++ { ++ case _GPE_INPUT_MANAGER_OPEN: ++ process_open_request (cmev->data.l[1]); ++ break; ++ case _GPE_INPUT_MANAGER_CLOSE: ++ process_close_request (cmev->data.l[1]); ++ break; ++ default: ++ fprintf (stderr, "received unknown _GPE_INPUT_MANAGER request %d\n", cmev->data.l[0]); ++ break; ++ } ++ } ++#ifndef DISABLE_OLD_PROTOCOL ++ else if (cmev->message_type == atoms[_MB_INPUT_REQUEST]) ++ { + /* De Activate */ + if (cmev->data.l[0] == 0 && mbinputmgr_method_active(Inpmgr_state)) + mbinputmgr_toggle_selected_method (Inpmgr_state); +@@ -278,8 +477,20 @@ + && !mbinputmgr_method_active(Inpmgr_state)) + mbinputmgr_toggle_selected_method (Inpmgr_state); + } ++#endif + } ++ else if (ev->type == UnmapNotify) ++ { ++ XUnmapEvent *uev = &ev->xunmap; + ++ process_close_request (uev->window); ++ } ++ else if (ev->type == ConfigureNotify && !docked_already) ++ { ++ docked_already = TRUE; ++ is_docked (); ++ } ++ + mb_menu_handle_xevent (PopupMenu, ev); + } + +@@ -347,11 +558,42 @@ + free(icon_path); + } + ++static Bool ++get_xevent_timed(Display* dpy, XEvent* event_return, struct timeval *tv) ++{ ++ if (tv == NULL) ++ { ++ 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; ++ } ++} ++ + int + main(int argc, char **argv) + { + int i; + MBPixbufImage *app_icon_img = NULL; ++ XEvent xevent; + + app = mb_tray_app_new ( "Input Selector", + resize_callback, +@@ -359,13 +601,13 @@ + &argc, + &argv ); + ++ dpy = mb_tray_app_xdisplay (app); ++ + Pixbuf = mb_pixbuf_new(mb_tray_app_xdisplay(app), + mb_tray_app_xscreen(app)); + +- AtomIMActivate = XInternAtom(mb_tray_app_xdisplay(app), +- "_MB_INPUT_REQUEST", False); ++ XInternAtoms (dpy, atom_names, sizeof (atom_names) / sizeof (atom_names[0]), False, atoms); + +- + PopupMenu = mb_menu_new (mb_tray_app_xdisplay(app), + mb_tray_app_xscreen(app)); + +@@ -399,17 +641,30 @@ + + mb_tray_app_set_xevent_callback (app, xevent_callback ); + ++ mb_tray_app_set_xevent_mask (app, SubstructureNotifyMask); ++ + mb_tray_app_set_button_callback (app, button_callback ); + + /* XXX set up dnotify to reload entrys only on _addition_ */ + ++#ifndef DISABLE_OLD_PROTOCOL + XSelectInput(mb_tray_app_xdisplay(app), + mb_tray_app_xrootwin(app), + SubstructureNotifyMask); ++#endif + ++ /* Not using mb_tray_app_main() to avoid libmb's broken get_xevent_timed() */ ++ mb_tray_app_main_init (app); ++ for (;;) ++ { ++ struct timeval tv, *tvp = NULL; + +- mb_tray_app_main (app); ++ if (get_timeout (&tv)) ++ tvp = &tv; + ++ if (get_xevent_timed (dpy, &xevent, tvp)) ++ mb_tray_handle_xevent (app, &xevent); ++ } ++ + return 0; + } +- diff --git a/packages/matchbox-applet-inputmanager/files/mbinputmgr-tray.c b/packages/matchbox-applet-inputmanager/files/mbinputmgr-tray.c new file mode 100644 index 0000000000..afebcfa581 --- /dev/null +++ b/packages/matchbox-applet-inputmanager/files/mbinputmgr-tray.c @@ -0,0 +1,415 @@ +/* + mbinputmgr + An inprogress panel app to manager available software input methods + + Copyright (c) 2003 Matthew Allum + + 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 "mbinputmgr.h" + +enum { + BUTTON_ACTIVATE, + BUTTON_MENU, +}; + +MBMenu *PopupMenu = NULL; +MBPixbuf *Pixbuf = NULL; +MBTrayApp *app; +int IconDim = 16; +int IconWidth = 26; +int TrayDepth = 0; /* width/height dep on orientation */ +int TrayAppLen = 0; /* len of tar app */ +MBInpmgrState *Inpmgr_state = NULL; +Bool ButtonIsDown = False; +int ButtonActive; +Atom AtomIMActivate; + +typedef struct ButtonImgs { + + MBPixbufImage *active; + MBPixbufImage *inactive; + +} ButtonImgs; + +void +paint_callback ( MBTrayApp *app, Drawable drw ) +{ + int x = 0, y = 0, ax, ay; + MBPixbufImage *img_bg = NULL, *img_icon = NULL, *img_selected = NULL; + int r = 0x33, g = 0x33, b = 0x33; + ButtonImgs *button; + int menu_button_offset = 0; + + /* The window has not yet been resized to a what we want */ + if ( TrayDepth == 0 ) return; + + if (mbinputmgr_method_active(Inpmgr_state)) + { + r = 0xcc, g = 0xcc, b = 0xcc; + } + + img_bg = mb_tray_app_get_background (app, Pixbuf); + + if (img_bg == NULL) + return; + + button = (ButtonImgs*)Inpmgr_state->MethodSelected->data; + + if (ButtonIsDown) + { + if (ButtonActive == BUTTON_MENU) + { + menu_button_offset = 2; + img_selected = button->inactive; + } + else img_selected = button->active; + } + else + { + img_selected = button->inactive; + } + + /* XXX abort for now if vertical */ + + if (mb_tray_app_tray_is_vertical (app)) + { + MBPixbufImage *img_tmp = NULL; + + if (mb_pixbuf_img_get_width(img_bg) != TrayDepth + || mb_pixbuf_img_get_height(img_bg) != TrayAppLen) + { + mb_pixbuf_img_free(Pixbuf, img_bg); + return; + } + + + /* GREAT BIG FUCKING HACK - + app gets expose on orientation change + with mb_tray_app_tray_is_vertical = TRUE, + but app->h & app->w not updated via missing configure event. + need to figure out a better fix than this !! + + NOTES: + - This expose can be basically ignored. + + */ + if (mb_pixbuf_img_get_width(img_bg) > mb_pixbuf_img_get_height(img_bg)) + { + mb_pixbuf_img_render_to_drawable (Pixbuf, img_bg, drw, 0, 0); + mb_pixbuf_img_free(Pixbuf, img_bg); + return; + } + + img_tmp = mb_pixbuf_img_scale (Pixbuf, + img_selected, + IconWidth, TrayDepth ); + + img_icon = mb_pixbuf_img_transform (Pixbuf, img_tmp, + MBPIXBUF_TRANS_ROTATE_90); + + mb_pixbuf_img_copy_composite (Pixbuf, img_bg, img_icon, + 0, 0, TrayDepth, IconWidth, 0, 0); + + ax = IconWidth+2 ; ay = 1 + menu_button_offset; + + for (x=4; x>=0; x--) + { + for (y=0; y < ((x-4)*-2)+1; y++) + mb_pixbuf_img_plot_pixel(Pixbuf, img_bg, ay, ax+x+y, 0x33, 0x33, 0x33); + ay++; + } + + mb_pixbuf_img_free(Pixbuf, img_tmp); + } + else + { + + if (mb_pixbuf_img_get_width(img_bg) != TrayAppLen + || mb_pixbuf_img_get_height(img_bg) != TrayDepth) + { + /* Dont paint till were sized how we want */ + mb_pixbuf_img_render_to_drawable (Pixbuf, img_bg, drw, 0, 0); + mb_pixbuf_img_free(Pixbuf, img_bg); + return; + } + + img_icon = mb_pixbuf_img_scale (Pixbuf, + img_selected, + IconWidth, TrayDepth ); + + mb_pixbuf_img_copy_composite (Pixbuf, img_bg, img_icon, + 0, 0, IconWidth, TrayDepth, 0, 0); + + ax = IconWidth+2; ay = 1 + menu_button_offset; + + for (x=4; x>=0; x--) + { + for (y=0; y < ((x-4)*-2)+1; y++) + mb_pixbuf_img_plot_pixel(Pixbuf, img_bg, ax+x+y, ay, 0x33, 0x33, 0x33); + ay++; + } + } + + mb_pixbuf_img_render_to_drawable (Pixbuf, img_bg, drw, 0, 0); + + /* Free up images */ + + mb_pixbuf_img_free( Pixbuf, img_bg ); + mb_pixbuf_img_free( Pixbuf, img_icon ); + +} + +void +resize_callback ( MBTrayApp *app, int w, int h ) +{ + /* Image should be 26/16 + 6 for arrow - should fix to be dynamic */ + + IconWidth = 26; + TrayAppLen = IconWidth + 12; + + if (mb_tray_app_tray_is_vertical (app)) + { + if (w > 16) + { + IconWidth = (26 * w)/16; + TrayAppLen = IconWidth + 12; + } + + TrayDepth = w; + mb_tray_app_request_size (app, TrayDepth, TrayAppLen ); + } + else + { + if (h > 16) + { + IconWidth = (26 * h)/16; + TrayAppLen = IconWidth + 12; + } + + TrayDepth = h; + mb_tray_app_request_size (app, TrayAppLen, TrayDepth ); + } +} + +void +button_callback (MBTrayApp *app, int x, int y, Bool is_released ) +{ + int abs_x, abs_y; + + if (mb_menu_is_active(PopupMenu)) + { + ButtonIsDown = True; + + if (is_released) + { + mb_menu_deactivate(PopupMenu); + ButtonIsDown = False; + } + + ButtonActive = BUTTON_MENU; + mb_tray_app_repaint (app); + return; + } + + if (is_released) + { + ButtonIsDown = False; + if ( (mb_tray_app_tray_is_vertical (app) && y > IconWidth) + || (!mb_tray_app_tray_is_vertical (app) && x > IconWidth) ) + { + mb_tray_app_get_absolute_coords (app, &abs_x, &abs_y); + + /* aligned top, position down a little */ + if (abs_y < 8) + { + int w, h; + mb_menu_get_root_menu_size(PopupMenu, &w, &h); + abs_y = h + IconDim + 2; + } + + mb_menu_activate(PopupMenu, abs_x, abs_y); + ButtonActive = BUTTON_MENU; + } + else + { + ButtonActive = BUTTON_ACTIVATE; + mbinputmgr_toggle_selected_method (Inpmgr_state); + } + + mb_tray_app_repaint (app); + } + else + { + if ( (mb_tray_app_tray_is_vertical (app) && y > IconWidth) + || (!mb_tray_app_tray_is_vertical (app) && x > IconWidth) ) + ButtonActive = BUTTON_MENU; + else + ButtonActive = BUTTON_ACTIVATE; + + ButtonIsDown = True; + mb_tray_app_repaint (app); + } +} + +void +xevent_callback (MBTrayApp *app, XEvent *ev) +{ + if (ev->type == ClientMessage) + { + XClientMessageEvent *cmev = (XClientMessageEvent *)&ev->xconfigure; + + if (cmev->message_type == AtomIMActivate) + { + /* De Activate */ + if (cmev->data.l[0] == 0 && mbinputmgr_method_active(Inpmgr_state)) + mbinputmgr_toggle_selected_method (Inpmgr_state); + /* Activate */ + else if (cmev->data.l[0] == 1 + && !mbinputmgr_method_active(Inpmgr_state)) + mbinputmgr_toggle_selected_method (Inpmgr_state); + } + } + + mb_menu_handle_xevent (PopupMenu, ev); +} + +void +menu_item_activated_callback (MBMenuItem *item_active) +{ + + mb_menu_deactivate(PopupMenu); + + mbinpmgr_change_selected_method (Inpmgr_state, + (InputMethod*)mb_menu_item_get_user_data(item_active)); + + mb_tray_app_repaint (app); +} + +void +load_icon (InputMethod *method) +{ + int x,y; + char *icon_path; + ButtonImgs *button = NULL; + + button = malloc(sizeof(ButtonImgs)); + memset(button, 0, sizeof(ButtonImgs)); + + /* + XXX : free existing images + */ + + icon_path = mb_dot_desktop_icon_get_full_path (NULL, /* util_get_theme?*/ + 16, + method->icon_name); + if (!icon_path) + { + fprintf(stderr, "mbinputmgr: Could not load %s\n", icon_path); + exit(1); + } + + if ((button->inactive = (void *)mb_pixbuf_img_new_from_file(Pixbuf, icon_path)) + == NULL) + { + fprintf(stderr, "Could not load %s\n", icon_path); + exit(1); + } + + button->active + = mb_pixbuf_img_clone(Pixbuf, button->inactive); + + for (x=0; x<mb_pixbuf_img_get_width(button->active); x++) + for (y=0; y<mb_pixbuf_img_get_height(button->active); y++) + { + int aa; + unsigned char r,g,b,a; + + mb_pixbuf_img_get_pixel(Pixbuf, button->active, x, y, &r, &g, &b, &a); + + aa = (int)a; + aa -= 0x80; if (aa < 0) aa = 0; + + mb_pixbuf_img_set_pixel_alpha( button->active, x, y, aa); + } + + method->data = (void *)button; + + free(icon_path); +} + +int +main(int argc, char **argv) +{ + int i; + MBPixbufImage *app_icon_img = NULL; + + app = mb_tray_app_new ( "Input Selector", + resize_callback, + paint_callback, + &argc, + &argv ); + + Pixbuf = mb_pixbuf_new(mb_tray_app_xdisplay(app), + mb_tray_app_xscreen(app)); + + AtomIMActivate = XInternAtom(mb_tray_app_xdisplay(app), + "_MB_INPUT_REQUEST", False); + + + PopupMenu = mb_menu_new (mb_tray_app_xdisplay(app), + mb_tray_app_xscreen(app)); + + /* mb_menu_set_icon_size(PopupMenu, IconDim); - no icons */ + + Inpmgr_state = mbinpmgr_init(); + + for (i=0; i<Inpmgr_state->NMethods; i++) + { + MBMenuItem *item; + load_icon(&Inpmgr_state->Methods[i]); + + item = mb_menu_new_item(PopupMenu, + mb_menu_get_root_menu(PopupMenu), + Inpmgr_state->Methods[i].name, + menu_item_activated_callback, + (void *)&Inpmgr_state->Methods[i], + 0 ); + } + + if ((app_icon_img = mb_pixbuf_img_new_from_file(Pixbuf, + DATADIR "/pixmaps/mbinputmgr.png")) != NULL) + { + mb_tray_app_set_icon(app, Pixbuf, app_icon_img); + } + else fprintf(stderr, "mbinputmgr: failed to load icon '%s'", + DATADIR "/pixmaps/mbinputmgr.png"); + + /* Make the tray app end up on right of mb panel */ + mb_tray_app_request_offset (app, -1); + + mb_tray_app_set_xevent_callback (app, xevent_callback ); + + mb_tray_app_set_button_callback (app, button_callback ); + + /* XXX set up dnotify to reload entrys only on _addition_ */ + + XSelectInput(mb_tray_app_xdisplay(app), + mb_tray_app_xrootwin(app), + SubstructureNotifyMask); + + + mb_tray_app_main (app); + + return 0; +} + diff --git a/packages/matchbox-applet-inputmanager/files/update-to-svn.diff b/packages/matchbox-applet-inputmanager/files/update-to-svn.diff new file mode 100644 index 0000000000..6ec68a0ea2 --- /dev/null +++ b/packages/matchbox-applet-inputmanager/files/update-to-svn.diff @@ -0,0 +1,33 @@ +--- /tmp/mbinputmgr-tray.c 2006-11-11 14:11:02.000000000 +0100 ++++ mb-applet-input-manager-0.6/mbinputmgr-tray.c 2006-11-11 14:11:43.638554000 +0100 +@@ -228,6 +228,15 @@ + || (!mb_tray_app_tray_is_vertical (app) && x > IconWidth) ) + { + mb_tray_app_get_absolute_coords (app, &abs_x, &abs_y); ++ ++ /* aligned top, position down a little */ ++ if (abs_y < 8) ++ { ++ int w, h; ++ mb_menu_get_root_menu_size(PopupMenu, &w, &h); ++ abs_y = h + IconDim + 2; ++ } ++ + mb_menu_activate(PopupMenu, abs_x, abs_y); + ButtonActive = BUTTON_MENU; + } +@@ -257,14 +266,10 @@ + { + if (ev->type == ClientMessage) + { +- printf("beep\n"); +- + XClientMessageEvent *cmev = (XClientMessageEvent *)&ev->xconfigure; + + if (cmev->message_type == AtomIMActivate) + { +- printf("beep\n"); +- + /* De Activate */ + if (cmev->data.l[0] == 0 && mbinputmgr_method_active(Inpmgr_state)) + mbinputmgr_toggle_selected_method (Inpmgr_state); |