lwlib-Xlw.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* The lwlib interface to "xlwmenu" menus.
  2. Copyright (C) 1992 Lucid, Inc.
  3. Copyright (C) 1994, 2000-2012 Free Software Foundation, Inc.
  4. This file is part of the Lucid Widget Library.
  5. The Lucid Widget Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9. The Lucid Widget Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Emacs; see the file COPYING. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA. */
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. #include <setjmp.h>
  21. #include <lisp.h>
  22. #include "lwlib-Xlw.h"
  23. #include <X11/StringDefs.h>
  24. #include <X11/IntrinsicP.h>
  25. #include <X11/ObjectP.h>
  26. #include <X11/CompositeP.h>
  27. #include <X11/Shell.h>
  28. #include "xlwmenu.h"
  29. #if 0
  30. #include <stdio.h>
  31. /* Print the complete X resource name of widget WIDGET to stderr.
  32. This is sometimes handy to have available. */
  33. void
  34. x_print_complete_resource_name (Widget widget)
  35. {
  36. int i;
  37. String names[100];
  38. for (i = 0; i < 100 && widget != NULL; ++i)
  39. {
  40. names[i] = XtName (widget);
  41. widget = XtParent (widget);
  42. }
  43. for (--i; i >= 1; --i)
  44. fprintf (stderr, "%s.", names[i]);
  45. fprintf (stderr, "%s\n", names[0]);
  46. }
  47. #endif /* 0 */
  48. /* Menu callbacks */
  49. /* Callback XtNhighlightCallback for Lucid menus. W is the menu
  50. widget, CLIENT_DATA contains a pointer to the widget_instance
  51. for the menu, CALL_DATA contains a pointer to the widget_value
  52. structure for the highlighted menu item. The latter may be null
  53. if there isn't any highlighted menu item. */
  54. static void
  55. highlight_hook (Widget w, XtPointer client_data, XtPointer call_data)
  56. {
  57. widget_instance *instance = (widget_instance *) client_data;
  58. if (instance->info->highlight_cb
  59. && !w->core.being_destroyed)
  60. instance->info->highlight_cb (w, instance->info->id, call_data);
  61. }
  62. static void
  63. enter_hook (Widget w, XtPointer client_data, XtPointer call_data)
  64. {
  65. highlight_hook (w, client_data, call_data);
  66. }
  67. static void
  68. leave_hook (Widget w, XtPointer client_data, XtPointer call_data)
  69. {
  70. highlight_hook (w, client_data, NULL);
  71. }
  72. static void
  73. pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
  74. {
  75. widget_instance* instance = (widget_instance*)client_data;
  76. widget_value* val;
  77. if (w->core.being_destroyed)
  78. return;
  79. val = lw_get_widget_value_for_widget (instance, w);
  80. if (instance->info->pre_activate_cb)
  81. instance->info->pre_activate_cb (w, instance->info->id,
  82. val ? val->call_data : NULL);
  83. }
  84. static void
  85. pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
  86. {
  87. widget_instance* instance = (widget_instance*)client_data;
  88. widget_value* contents_val = (widget_value*)call_data;
  89. widget_value* widget_val;
  90. XtPointer widget_arg;
  91. if (w->core.being_destroyed)
  92. return;
  93. if (instance->info->selection_cb && contents_val && contents_val->enabled
  94. && !contents_val->contents)
  95. instance->info->selection_cb (w, instance->info->id,
  96. contents_val->call_data);
  97. widget_val = lw_get_widget_value_for_widget (instance, w);
  98. widget_arg = widget_val ? widget_val->call_data : NULL;
  99. if (instance->info->post_activate_cb)
  100. instance->info->post_activate_cb (w, instance->info->id, widget_arg);
  101. }
  102. /* creation functions */
  103. static Widget
  104. xlw_create_menubar (widget_instance *instance)
  105. {
  106. Widget widget;
  107. Arg al[5];
  108. int ac = 0;
  109. XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
  110. #ifdef emacs
  111. XtSetArg (al[ac], XtNshowGrip, 0); ac++;
  112. XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
  113. XtSetArg (al[ac], XtNallowResize, 1); ac++;
  114. #endif
  115. /* This used to use XtVaCreateWidget, but an old Xt version
  116. has a bug in XtVaCreateWidget that frees instance->info->name. */
  117. widget
  118. = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
  119. instance->parent, al, ac);
  120. XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
  121. XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
  122. XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
  123. XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
  124. return widget;
  125. }
  126. static Widget
  127. xlw_create_popup_menu (widget_instance *instance)
  128. {
  129. Widget popup_shell
  130. = XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
  131. instance->parent, NULL, 0);
  132. Widget widget;
  133. Arg al[2];
  134. int ac = 0;
  135. XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
  136. XtSetArg (al[ac], XtNhorizontal, False); ac++;
  137. /* This used to use XtVaManagedCreateWidget, but an old Xt version
  138. has a bug in XtVaManagedCreateWidget that frees instance->info->name. */
  139. widget
  140. = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
  141. popup_shell, al, ac);
  142. XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
  143. XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
  144. XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
  145. return popup_shell;
  146. }
  147. widget_creation_entry
  148. xlw_creation_table [] =
  149. {
  150. {"menubar", xlw_create_menubar},
  151. {"popup", xlw_create_popup_menu},
  152. {NULL, NULL}
  153. };
  154. Boolean
  155. lw_lucid_widget_p (Widget widget)
  156. {
  157. WidgetClass the_class = XtClass (widget);
  158. if (the_class == xlwMenuWidgetClass)
  159. return True;
  160. if (the_class == overrideShellWidgetClass)
  161. return (XtClass (((CompositeWidget)widget)->composite.children [0])
  162. == xlwMenuWidgetClass);
  163. return False;
  164. }
  165. void
  166. xlw_update_one_widget (widget_instance* instance, Widget widget,
  167. widget_value* val, Boolean deep_p)
  168. {
  169. Arg al[1];
  170. /* This used to use XtVaSetValues, but some old Xt versions
  171. that have a bug in XtVaCreateWidget might have it here too. */
  172. XtSetArg (al[0], XtNmenu, instance->info->val);
  173. XtSetValues (widget, al, 1);
  174. }
  175. void
  176. xlw_update_one_value (widget_instance *instance,
  177. Widget widget,
  178. widget_value *val)
  179. {
  180. return;
  181. }
  182. void
  183. xlw_pop_instance (widget_instance* instance, Boolean up)
  184. {
  185. }
  186. void
  187. xlw_popup_menu (Widget widget, XEvent *event)
  188. {
  189. XlwMenuWidget mw;
  190. if (!XtIsShell (widget))
  191. return;
  192. mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
  193. if (event)
  194. XtCallActionProc ((Widget) mw, "start", event, NULL, 0);
  195. else
  196. {
  197. XEvent dummy;
  198. XButtonPressedEvent *bd = &dummy.xbutton;
  199. bd->type = ButtonPress;
  200. bd->serial = 0;
  201. bd->send_event = 0;
  202. bd->display = XtDisplay (widget);
  203. bd->window = XtWindow (XtParent (widget));
  204. bd->time = CurrentTime;
  205. bd->button = 0;
  206. XQueryPointer (bd->display, bd->window, &bd->root,
  207. &bd->subwindow, &bd->x_root, &bd->y_root,
  208. &bd->x, &bd->y, &bd->state);
  209. XtCallActionProc ((Widget) mw, "start", &dummy, NULL, 0);
  210. }
  211. }
  212. /* Destruction of instances */
  213. void
  214. xlw_destroy_instance (widget_instance *instance)
  215. {
  216. if (instance->widget)
  217. XtDestroyWidget (instance->widget);
  218. }