Add a configurable X11 backend accepted/tizen/common/20140904.154930 submit/accepted/tizen_common/20140904.133032 submit/accepted/tizen_common/20140904.153927 submit/tizen/20140904.153959
authorManuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Thu, 4 Sep 2014 12:52:44 +0000 (14:52 +0200)
committerManuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Thu, 4 Sep 2014 13:02:55 +0000 (15:02 +0200)
If libwlmessage is built with "--enable-x11", it will now
use its fresh-new X11 backend to display popups.

Just like the Wayland one, the X11 backend uses no toolkit
(few dependencies). It looks similar, too.

Signed-off-by: Manuel Bachmann <manuel.bachmann@open.eurogiciel.org>
Makefile.am
configure.ac
libwlmessage-wl.c [moved from libwlmessage.c with 100% similarity]
libwlmessage-x11.c [new file with mode: 0644]
packaging/libwlmessage.spec

index 3a8f761..875773f 100644 (file)
@@ -17,8 +17,16 @@ lib_LTLIBRARIES = libwlmessage.la
 
 include_HEADERS = libwlmessage.h
 
-libwlmessage_la_SOURCES =                                      \
-       libwlmessage.c                                  \
+libwlmessage_la_SOURCES =
+
+if ENABLE_X11
+libwlmessage_la_SOURCES +=                             \
+       libwlmessage-x11.c
+endif
+
+if ENABLE_WAYLAND
+libwlmessage_la_SOURCES +=                             \
+       libwlmessage-wl.c                               \
        toytoolkit/shared/frame.c                       \
        toytoolkit/shared/image-loader.c                \
        toytoolkit/shared/cairo-util.c                  \
@@ -28,6 +36,7 @@ libwlmessage_la_SOURCES =                                     \
        toytoolkit/text-protocol.c                      \
        toytoolkit/workspaces-protocol.c                \
        toytoolkit/window.c
+endif
 
 libwlmessage_la_LDFLAGS = -export-dynamic
 libwlmessage_la_CPPFLAGS = $(AM_CPPFLAGS) -Wno-unused-result
index 3d51f31..257f659 100644 (file)
@@ -34,6 +34,20 @@ AC_SUBST(DLOPEN_LIBS)
 
 AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate])
 
+AC_ARG_ENABLE(x11, [  --enable-x11],,
+              enable_x11=no)
+AM_CONDITIONAL(ENABLE_X11, test x$enable_x11 = xyes)
+if test x$enable_x11 = xyes; then
+       platform_libs="$platform_libs x11 xt xaw7"
+fi
+
+AC_ARG_ENABLE(wayland, [  --enable-wayland],,
+              enable_wayland=yes)
+AM_CONDITIONAL(ENABLE_WAYLAND, test x$enable_wayland = xyes)
+if test x$enable_wayland = xyes; then
+       platform_libs="$platform_libs wayland-client wayland-cursor xkbcommon"
+fi
+
 AC_ARG_ENABLE(xdg-shell,
               AS_HELP_STRING([--enable-xdg-shell],
                              [build with XDG-Shell support (Weston 1.5.0)]),
@@ -81,6 +95,10 @@ if test "x$cairo_modules" = "xcairo-glesv2"; then
 AC_DEFINE([USE_CAIRO_GLESV2], [1], [Use the GLESv2 GL cairo backend])
 fi
 
+if test x$enable_wayland = xyes && test x$enable_egl = xyes; then
+       cairo_modules="$cairo_modules wayland-egl"
+fi
+
 PKG_CHECK_MODULES(PIXMAN, [pixman-1])
 PKG_CHECK_MODULES(PNG, [libpng])
 
@@ -94,11 +112,11 @@ AC_SUBST(JPEG_LIBS)
 
 PKG_CHECK_MODULES(GLIB, [glib-2.0 gio-2.0])
 
-PKG_CHECK_MODULES(CLIENT, [wayland-client cairo >= 1.10.0 xkbcommon wayland-cursor])
+PKG_CHECK_MODULES(CLIENT, [$platform_libs cairo >= 1.10.0])
 
   # Only check for cairo-egl if a GL or GLES renderer requested
   AS_IF([test "x$cairo_modules" = "xcairo-glesv2"], [
-    PKG_CHECK_MODULES(CAIRO_EGL, [wayland-egl egl >= 7.10 cairo-egl >= 1.11.3 $cairo_modules],
+    PKG_CHECK_MODULES(CAIRO_EGL, [egl >= 7.10 cairo-egl >= 1.11.3 $cairo_modules],
                       [have_cairo_egl=yes], [have_cairo_egl=no])
     AS_IF([test "x$have_cairo_egl" = "xyes"],
          [AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])],
similarity index 100%
rename from libwlmessage.c
rename to libwlmessage-wl.c
diff --git a/libwlmessage-x11.c b/libwlmessage-x11.c
new file mode 100644 (file)
index 0000000..0c3b2c1
--- /dev/null
@@ -0,0 +1,718 @@
+/* Copyright © 2014 Manuel Bachmann */
+
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xaw/Command.h>
+#include <cairo/cairo-xlib.h>
+
+#include "libwlmessage.h"
+#define MAX_LINES 6
+#define MAX_BUTTONS 3
+
+
+struct message_window {
+       Widget window;
+
+       char *message;
+       char *title;
+       char *textfield;
+       int frame_type; /* for titlebuttons */
+       int resizable;
+       cairo_surface_t *icon;
+       int buttons_nb;
+       struct button *button_list[MAX_BUTTONS];
+
+       struct wlmessage *wlmessage;
+};
+
+struct button {
+       Widget button;
+
+       char *caption;
+       int value;
+       struct message_window *message_window;
+};
+
+struct wlmessage {
+       Display *display;
+       XtAppContext app;
+       struct message_window *message_window;
+       int return_value;
+       int timeout;
+};
+
+struct widget_map {
+       cairo_surface_t *icon;
+       Widget label;
+       Widget entry;
+       Widget form_b;
+       struct button **button_list;
+       int buttons_nb;
+       int lines_nb;
+};
+
+ /* ---------------------------------------- */
+
+ /* -- HELPER FUNCTIONS AND STRUCTURES -- */
+
+#define _MOTIF_WM_HINTS_FUNCTIONS   (1L << 0)
+#define _MOTIF_WM_HINTS_DECORATIONS (1L << 1)
+
+#define _MOTIF_WM_FUNC_ALL      (1L << 0)
+#define _MOTIF_WM_FUNC_RESIZE   (1L << 1)
+#define _MOTIF_WM_FUNC_MOVE     (1L << 2)
+#define _MOTIF_WM_FUNC_MINIMIZE (1L << 3)
+#define _MOTIF_WM_FUNC_MAXIMIZE (1L << 4)
+#define _MOTIF_WM_FUNC_CLOSE    (1L << 5)
+
+#define _MOTIF_WM_DECOR_ALL      (1L << 0)
+#define _MOTIF_WM_DECOR_MINIMIZE (1L << 5)
+#define _MOTIF_WM_DECOR_MAXIMIZE (1L << 6)
+
+typedef struct {
+       unsigned int flags;
+       unsigned int functions;
+       unsigned int decorations;
+       int inputMode;
+       unsigned int status;
+} WMHints;
+
+void *
+xzalloc(size_t size)
+{
+       return calloc(1, size);
+}
+
+int
+get_number_of_lines (char *text)
+{
+       int lines_num = 0;
+
+       gchar **lines = g_strsplit (text, "\n", -1);
+
+       if (lines) {
+               while ((lines[lines_num] != NULL) && (lines_num < MAX_LINES))
+                       lines_num++;
+               g_strfreev (lines);
+       }
+
+       return lines_num;
+}
+
+int
+get_max_length_of_lines (char *text)
+{
+       int lines_num = 0;
+       int length = 0;
+
+       gchar **lines = g_strsplit (text, "\n", -1);
+
+       if (lines) {
+               while ((lines[lines_num] != NULL) && (lines_num < MAX_LINES)) {
+                       if (strlen (lines[lines_num]) > length)
+                               length = strlen (lines[lines_num]);
+                       lines_num++;
+               }
+               g_strfreev (lines);
+       }
+
+       return length;
+}
+
+char **
+get_lines (char *text)
+{
+       gchar **lines = g_strsplit (text, "\n", -1);
+
+       return lines;
+}
+
+ /* ---------------------------------------- */
+
+ /* -- HANDLERS -- */
+
+void
+bt_on_validate (Widget widget, XtPointer data, XtPointer callback_data)
+{
+       struct button *button = (struct button *) data;
+
+       button->message_window->wlmessage->return_value = button->value;
+
+       XtAppSetExitFlag (button->message_window->wlmessage->app);
+}
+
+static void
+bt_on_pointer (Widget widget, XtPointer data, XEvent *event, Boolean *d)
+{
+       Widget button = widget;
+       int x, y;
+       
+       switch (event->type) {
+               case ButtonPress:
+                       XtVaGetValues (button, XtNx, &x, XtNy, &y, NULL);
+                       XtMoveWidget (button, x+1, y+1);
+                       XtVaSetValues (button, XtVaTypedArg, XtNbackground, XtRString, "black", strlen("black")+1, NULL);
+                       XtVaSetValues (button, XtVaTypedArg, XtNforeground, XtRString, "white", strlen("white")+1, NULL);
+                       break;
+               case ButtonRelease:
+                       XtVaGetValues (button, XtNx, &x, XtNy, &y, NULL);
+                       XtMoveWidget (button, x-1, y-1);
+                       XtVaSetValues (button, XtVaTypedArg, XtNbackground, XtRString, "white", strlen("white")+1, NULL);
+                       XtVaSetValues (button, XtVaTypedArg, XtNforeground, XtRString, "black", strlen("black")+1, NULL);
+                       break;
+               case EnterNotify:
+                       XtVaSetValues (button, XtVaTypedArg, XtNbackground, XtRString, "white", strlen("white")+1, NULL);
+                       break;
+               case LeaveNotify:
+                       XtVaSetValues (button, XtVaTypedArg, XtNbackground, XtRString, "light gray", strlen("light gray")+1, NULL);
+                       break;
+               default:
+                       break;
+       }
+}
+
+static void
+resize_handler (Widget widget, XtPointer data, XEvent *event, Boolean *d)
+{
+       Widget form = widget;
+       struct widget_map *map = (struct widget_map *)data;
+       short width, height;
+       int i;
+
+       if (event->type == ConfigureNotify) {
+               XtConfigureWidget (map->label, (event->xconfigure.width - (event->xconfigure.width-100)) / 2,
+                                              (!map->icon ? 10 : 80),
+                                              event->xconfigure.width - 100,
+                                              map->lines_nb * 20,
+                                              1);
+               if (map->entry)
+                       XtConfigureWidget (map->entry, (event->xconfigure.width - (event->xconfigure.width-150)) /2,
+                                                      event->xconfigure.height - 80,
+                                                      event->xconfigure.width - 150,
+                                                      20,
+                                                      1);
+               XtConfigureWidget (map->form_b, (event->xconfigure.width - (event->xconfigure.width-200)) / 2,
+                                                event->xconfigure.height - 55,
+                                                event->xconfigure.width - 200, 50,
+                                                1);
+               for (i = 0; i < map->buttons_nb; i++) {
+                       XtConfigureWidget (map->button_list[i]->button, ((event->xconfigure.width - 200) /(map->buttons_nb*80)) + i*80 + (i+1)*10,
+                                                       10,
+                                                       80, 30,
+                                                       1);
+               }
+
+                /* force redraw */
+               event->type = Expose;
+       }
+
+       if (event->type = Expose && map->icon) {
+               XtVaGetValues (form, XtNwidth, &width,
+                                    XtNheight, &height,
+                                    NULL);
+               cairo_surface_t *cs = cairo_xlib_surface_create (XtDisplay(form), XtWindow(form), DefaultVisual(XtDisplay(form), 0), width, height);
+               cairo_t *cr = cairo_create (cs);
+               cairo_set_source_surface (cr, map->icon, (width - 64)/2, 10);
+               cairo_paint (cr);
+               cairo_destroy (cr);
+               cairo_surface_destroy (cs);
+       }
+}
+
+static void
+key_handler (Widget widget, XtPointer data, XEvent *event, Boolean *d)
+{
+       struct message_window *message_window = (struct message_window *) data;
+       Widget entry = widget;
+       KeySym sym;
+       XawTextPosition pos;
+       XawTextBlock buffer;
+
+       if (event->type == KeyPress) {
+               sym = XLookupKeysym (&event->xkey, 0);
+               if (sym == XK_Return || sym == XK_KP_Enter) {
+                       XtAppSetExitFlag (message_window->wlmessage->app);
+               } else {
+                        /* prevent a text longer than 20 characters */
+                       XtVaGetValues (entry, XtNinsertPosition, &pos, NULL);
+                       if (pos > 30) {
+                               buffer.firstPos = 0; buffer.length = 1;
+                               buffer.ptr = "\n"; buffer.format = FMT8BIT;
+                               XawTextReplace (entry, pos-1, pos, &buffer);
+                               XtVaSetValues (entry, XtNinsertPosition, 30, NULL);
+                       }
+               }
+       }
+}
+
+ /* ---------------------------------------- */
+
+void
+wlmessage_set_title (struct wlmessage *wlmessage, char *title)
+{
+       if ((!wlmessage) || (!title))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       if (message_window->title)
+               free (message_window->title);
+
+       message_window->title = strdup (title);
+}
+
+char *
+wlmessage_get_title (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return NULL;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       return message_window->title;
+}
+
+void
+wlmessage_set_titlebuttons (struct wlmessage *wlmessage, enum wlmessage_titlebutton titlebuttons)
+{
+       if (!wlmessage)
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       message_window->frame_type = _MOTIF_WM_FUNC_MOVE;
+       
+       if (titlebuttons && WLMESSAGE_TITLEBUTTON_MINIMIZE)
+               message_window->frame_type = message_window->frame_type | _MOTIF_WM_FUNC_MINIMIZE;
+       if (titlebuttons && WLMESSAGE_TITLEBUTTON_MAXIMIZE)
+               message_window->frame_type = message_window->frame_type | _MOTIF_WM_FUNC_MAXIMIZE;
+       if (titlebuttons && WLMESSAGE_TITLEBUTTON_CLOSE)
+               message_window->frame_type = message_window->frame_type | _MOTIF_WM_FUNC_CLOSE;
+}
+
+enum wlmessage_titlebutton
+wlmessage_get_titlebuttons (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return 0;
+
+       struct message_window *message_window = wlmessage->message_window;
+       enum wlmessage_titlebutton titlebuttons;
+
+       titlebuttons = WLMESSAGE_TITLEBUTTON_NONE;
+
+       if (message_window->frame_type && _MOTIF_WM_FUNC_MINIMIZE)
+               titlebuttons = titlebuttons | WLMESSAGE_TITLEBUTTON_MINIMIZE;
+       if (message_window->frame_type && _MOTIF_WM_FUNC_MAXIMIZE)
+               titlebuttons = titlebuttons | WLMESSAGE_TITLEBUTTON_MAXIMIZE;
+       if (message_window->frame_type && _MOTIF_WM_FUNC_CLOSE)
+               titlebuttons = titlebuttons | WLMESSAGE_TITLEBUTTON_CLOSE;
+
+       return titlebuttons;
+}
+
+void
+wlmessage_set_noresize (struct wlmessage *wlmessage, unsigned int not_resizable)
+{
+       if (!wlmessage)
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       message_window->resizable = !not_resizable;
+}
+
+unsigned int
+wlmessage_get_noresize (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return 0;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       return !message_window->resizable;
+}
+
+void
+wlmessage_set_icon (struct wlmessage *wlmessage, char *icon_path)
+{
+       if ((!wlmessage) || (!icon_path))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+       cairo_surface_t *icon;
+       cairo_status_t status;
+
+       icon = cairo_image_surface_create_from_png (icon_path);
+       status = cairo_surface_status (icon);
+
+       if (status == CAIRO_STATUS_SUCCESS) {
+                       message_window->icon = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 64, 64);
+                       cairo_t *icon_cr = cairo_create (message_window->icon);
+                        /* rescale to 64x64 */
+                       int width = cairo_image_surface_get_width (icon);
+                       int height = cairo_image_surface_get_height (icon);
+                       if (width != height != 64) {
+                               double ratio = ((64.0/width) < (64.0/height) ? (64.0/width) : (64.0/height));
+                               cairo_scale (icon_cr, ratio, ratio);
+                       }
+                       cairo_set_source_surface (icon_cr, icon, 0.0, 0.0);
+                       cairo_paint (icon_cr);
+                       cairo_destroy (icon_cr);
+                       cairo_surface_destroy (icon);
+       }
+
+}
+
+void
+wlmessage_set_message (struct wlmessage *wlmessage, char *message)
+{
+       if ((!wlmessage) || (!message))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       if (message_window->message)
+               free (message_window->message);
+
+       message_window->message = strdup (message);
+}
+
+char *
+wlmessage_get_message (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return NULL;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       return message_window->message;
+}
+
+void
+wlmessage_set_message_file (struct wlmessage *wlmessage, char *file_path)
+{
+       if ((!wlmessage) || (!file_path))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+       FILE *file = NULL;
+       char *text = NULL;
+       int i, c;
+
+       file = fopen (file_path, "r");
+       if (!file) {
+               return;
+       } else {
+               i = 0;
+               text = malloc (sizeof(char));
+               while (c != EOF) {
+                       c = fgetc (file);
+                       if (c != EOF) {
+                               realloc (text, (i+1)*sizeof(char));
+                               text[i] = c;
+                               i++;
+                       }
+               }
+               realloc (text, (i+1)*sizeof(char));
+               text[i] = '\0';
+               fclose (file);
+       }
+
+       if (message_window->message)
+               free (message_window->message);
+
+       message_window->message = text;
+}
+
+void
+wlmessage_add_button (struct wlmessage *wlmessage, unsigned int index, char *caption)
+{
+       if ((!wlmessage) || (!caption))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+       struct button *button;
+
+       if (message_window->buttons_nb == MAX_BUTTONS)
+               return;
+
+       button = xzalloc (sizeof *button);
+       button->caption = strdup (caption);
+       button->value = index;
+       button->message_window = message_window;
+
+       message_window->button_list[message_window->buttons_nb] = button;
+       message_window->buttons_nb++;
+}
+
+void
+wlmessage_delete_button (struct wlmessage *wlmessage, unsigned int index)
+{
+       if (!wlmessage)
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+       struct button *button;
+       int total, i;
+
+       total = message_window->buttons_nb;
+       for (i = 0; i < total; i++) {
+               button = message_window->button_list[i];
+               if (button->value == index) {
+                       free (button->caption);
+                       free (button);
+                       message_window->buttons_nb--;
+               }
+       }
+}
+
+void
+wlmessage_set_default_button (struct wlmessage *wlmessage, unsigned int index)
+{
+       if (!wlmessage)
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+       struct button *button;
+       int i;
+
+       for (i = 0; i < message_window->buttons_nb; i++) {
+               button = message_window->button_list[i];
+               if (button->value == index)
+                               wlmessage->return_value = button->value;
+       }
+}
+
+void
+wlmessage_set_textfield (struct wlmessage *wlmessage, char *default_text)
+{
+       if ((!wlmessage) || (!default_text))
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       if (message_window->textfield)
+               free (message_window->textfield);
+
+       message_window->textfield = strdup (default_text);
+}
+
+char *
+wlmessage_get_textfield (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return NULL;
+
+       struct message_window *message_window = wlmessage->message_window;
+       
+       return message_window->textfield;
+}
+
+void
+wlmessage_set_timeout (struct wlmessage *wlmessage, unsigned int timeout)
+{
+       if (!wlmessage)
+               return;
+
+       wlmessage->timeout = timeout;
+}
+
+unsigned int
+wlmessage_get_timeout (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return 0;
+
+       return wlmessage->timeout;
+}
+
+int
+wlmessage_show (struct wlmessage *wlmessage, char **input_text)
+{
+       if (!wlmessage)
+               return 0;
+
+       struct message_window *message_window = wlmessage->message_window;
+       Widget form, label, entry, form_b;
+       XWindowChanges wc;
+       WMHints wm_hints;
+       Atom hintsatom;
+       int extended_width = 0;
+       int lines_nb = 0;
+       int argc_v = 3;
+       gchar **argv_v = g_strsplit ("libwlmessage -geometry 320x200", " ", -1);
+
+       message_window->window = XtVaAppInitialize (&wlmessage->app, "wlmessage", NULL, 0, &argc_v, argv_v, NULL, NULL);
+
+       wlmessage->display = XtDisplay (message_window->window);
+       if (!wlmessage->display) {
+               fprintf (stderr, "Failed to get X11 display object !\n");
+               return -1;
+       }
+
+       /*if (wlmessage->timeout)
+               display_set_timeout (wlmessage->display, wlmessage->timeout);*/
+
+        /* add main form */
+       form = XtCreateManagedWidget ("form", formWidgetClass, message_window->window, NULL, 0);
+       XtVaSetValues (form, XtVaTypedArg, XtNbackground, XtRString, "light slate grey", strlen("light slate grey")+1, NULL);
+
+        /* add message */
+       label = XtCreateManagedWidget ("message", labelWidgetClass, form, NULL, 0);
+       XtVaSetValues (label, XtVaTypedArg, XtNbackground, XtRString, "light slate grey", strlen("light slate grey")+1, NULL);
+       XtVaSetValues (label, XtVaTypedArg, XtNborderColor, XtRString, "light slate grey", strlen("light slate grey")+1, NULL);
+       XtVaSetValues (label, XtNlabel, (String) message_window->message,
+                             XtNborderWidth, 0,
+                             NULL);
+
+        /* add entry */
+       if (message_window->textfield) {
+               entry = XtCreateManagedWidget ("entry", asciiTextWidgetClass, form, NULL, 0);
+               XtVaSetValues (entry, XtNstring, (String) message_window->textfield,
+                                     XtNeditType, XawtextEdit,
+                                     XtNwrap, XawtextWrapWord,
+                                     XtNautoFill, True,
+                                     XtNleftColumn, 10,
+                                     XtNrightColumn, 20,
+                                     XtNjustify, XtJustifyCenter,
+                                     XtNfromVert, label,
+                                     NULL);
+       }
+
+        /* add buttons form */
+       form_b = XtCreateManagedWidget ("form_b", formWidgetClass, form, NULL, 0);
+       XtVaSetValues (form_b, XtVaTypedArg, XtNbackground, XtRString, "light slate grey", strlen("light slate grey")+1, NULL);
+       XtVaSetValues (form_b, XtVaTypedArg, XtNborderColor, XtRString, "light slate grey", strlen("light slate grey")+1, NULL);
+       XtVaSetValues (form_b, XtNborderWidth, 0, NULL);
+       if (message_window->textfield)
+               XtVaSetValues (form_b, XtNfromVert, entry, NULL);
+       else
+               XtVaSetValues (form_b, XtNfromVert, label, NULL);
+
+        /* add buttons */
+       struct button *button, *prev_button = NULL;
+       int i;
+       for (i = 0; i < message_window->buttons_nb; i++) {
+               button = message_window->button_list[i];
+               button->button = XtCreateManagedWidget (button->caption, commandWidgetClass, form_b, NULL, 0);
+               XtVaSetValues (button->button, XtVaTypedArg, XtNbackground, XtRString, "light gray", strlen("light gray")+1, NULL);
+               XtVaSetValues (button->button, XtNhighlightThickness, 0, NULL);
+               if (prev_button) {
+                       XtVaSetValues (button->button, XtNfromHoriz, prev_button->button, NULL);
+               }
+               XtAddEventHandler (button->button, ButtonPressMask | ButtonReleaseMask |
+                                          EnterWindowMask | LeaveWindowMask,
+                                          True, bt_on_pointer, NULL);
+               XtAddCallback (button->button, XtNcallback, bt_on_validate, button);
+               prev_button = button;
+       }
+
+        /* global resize handler */
+       extended_width = (get_max_length_of_lines (message_window->message)) - 35;
+        if (extended_width < 0) extended_width = 0;
+       lines_nb = get_number_of_lines (message_window->message);
+
+       struct widget_map *map = xzalloc (sizeof *map);
+       map->icon = message_window->icon;
+       map->label = label;
+       map->entry = entry;
+       map->form_b = form_b;
+       map->button_list = message_window->button_list;
+       map->buttons_nb = message_window->buttons_nb;
+       map->lines_nb = lines_nb;
+       XtAddEventHandler (form, StructureNotifyMask | ExposureMask,
+                                True, resize_handler, map);
+
+        /* global keyboard handler */
+       XtAddEventHandler (entry, KeyPressMask, True, key_handler, message_window);
+
+        /* general actions (title, size, decorations...) */
+       XtRealizeWidget (message_window->window);
+
+       XStoreName (wlmessage->display, XtWindow(message_window->window), message_window->title);
+
+       wc.width = 420 + extended_width*10;
+       wc.height = 240 + lines_nb*20; /*+ (!message_window->entry ? 0 : 1)*32
+                                      + (!message_window->buttons_nb ? 0 : 1)*32);*/
+       XConfigureWindow (wlmessage->display, XtWindow(message_window->window), CWWidth | CWHeight, &wc);
+
+       hintsatom = XInternAtom (wlmessage->display, "_MOTIF_WM_HINTS", False);
+       if (hintsatom) {
+               wm_hints.flags = _MOTIF_WM_HINTS_FUNCTIONS;
+               wm_hints.functions = message_window->frame_type;
+               /*wm_hints.decorations = False; *//* disables the border */
+               XChangeProperty (wlmessage->display, XtWindow(message_window->window),
+                                hintsatom, hintsatom, 32, PropModeReplace,
+                                (unsigned char *) &wm_hints, 5);
+               /* refresh here ! */
+       }
+
+        /* main loop */
+       XtAppMainLoop (wlmessage->app);
+
+       if (entry) {
+               XawTextBlock buffer;
+               XawTextSourceRead (XawTextGetSource(entry), 0, &buffer, 30);
+               *input_text = strdup (g_strstrip(buffer.ptr));
+       }
+
+       return wlmessage->return_value;
+}
+
+struct wlmessage *
+wlmessage_create ()
+{
+       struct wlmessage *wlmessage;
+
+       wlmessage = xzalloc (sizeof *wlmessage);
+       wlmessage->return_value = 0;
+       wlmessage->timeout = 0;
+
+       wlmessage->message_window = xzalloc (sizeof *wlmessage->message_window);
+       wlmessage->message_window->title = strdup ("wlmessage");
+       wlmessage->message_window->frame_type = _MOTIF_WM_FUNC_ALL;
+       wlmessage->message_window->resizable = 1;
+       wlmessage->message_window->icon = NULL;
+       wlmessage->message_window->message = NULL;
+       wlmessage->message_window->textfield = NULL;
+       wlmessage->message_window->buttons_nb = 0;
+       wlmessage->message_window->wlmessage = wlmessage;
+
+       return wlmessage;
+}
+
+void
+wlmessage_destroy (struct wlmessage *wlmessage)
+{
+       if (!wlmessage)
+               return;
+
+       struct message_window *message_window = wlmessage->message_window;
+
+       if (message_window->icon)
+               cairo_surface_destroy (message_window->icon);
+       //if (message_window->window)
+       //      window_destroy (message_window->window);
+       if (message_window->title)
+               free (message_window->title);
+       if (message_window->message)
+               free (message_window->message);
+       if (message_window->textfield)
+               free (message_window->textfield);
+       free (message_window);
+
+       free (wlmessage);
+}
+
+ /* ---------------------------------------- */
+
index 1ee7f60..e6eb4f8 100644 (file)
@@ -1,3 +1,4 @@
+%bcond_with x
 %bcond_with wayland
 
 Name:           libwlmessage
@@ -16,10 +17,17 @@ BuildRequires:  libjpeg-devel
 BuildRequires:  xz
 BuildRequires:  pkgconfig
 BuildRequires:  pkgconfig(libpng)
+%if %{with x}
+BuildRequires:  pkgconfig(x11)
+BuildRequires:  pkgconfig(xt)
+BuildRequires:  pkgconfig(xaw7)
+%endif
+%if %{with wayland}
 BuildRequires:  pkgconfig(xkbcommon)
 BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  pkgconfig(wayland-cursor)
 BuildRequires:  pkgconfig(wayland-egl)
+%endif
 BuildRequires:  pkgconfig(egl)
 BuildRequires:  pkgconfig(glesv2)
 BuildRequires:  pkgconfig(pixman-1)
@@ -29,10 +37,6 @@ BuildRequires:  pkgconfig(cairo-glesv2)
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gio-2.0)
 
-%if !%{with wayland}
-ExclusiveArch:
-%endif
-
 %description
 libwlmessage is a very tiny and toolkit-independent library, able to display interactive dialog boxes under Wayland.
 
@@ -49,7 +53,13 @@ Development files for %{name}
 cp %{SOURCE1} .
 
 %build
-%reconfigure --enable-xdg-shell
+%reconfigure \
+%if %{with x}
+ --enable-x11 --disable-wayland
+%else
+ --disable-x11 --enable-wayland --enable-xdg-shell
+%endif
+
 make %{?_smp_mflags}
 
 %install