diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/Makefile.am | 33 | ||||
-rw-r--r-- | src/tools/marco-grayscale.c | 109 | ||||
-rw-r--r-- | src/tools/marco-mag.c | 278 | ||||
-rw-r--r-- | src/tools/marco-message.c | 187 | ||||
-rw-r--r-- | src/tools/marco-window-demo.c | 1016 | ||||
-rw-r--r-- | src/tools/marco-window-demo.png | bin | 0 -> 3453 bytes |
6 files changed, 1623 insertions, 0 deletions
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am new file mode 100644 index 00000000..031ef961 --- /dev/null +++ b/src/tools/Makefile.am @@ -0,0 +1,33 @@ +@INTLTOOL_DESKTOP_RULE@ + +icondir=$(pkgdatadir)/icons +icon_DATA=marco-window-demo.png + +INCLUDES=@MARCO_WINDOW_DEMO_CFLAGS@ @MARCO_MESSAGE_CFLAGS@ \ + -DMARCO_ICON_DIR=\"$(pkgdatadir)/icons\" \ + -DMARCO_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" + +marco_message_SOURCES= \ + marco-message.c + +marco_window_demo_SOURCES= \ + marco-window-demo.c + +marco_mag_SOURCES= \ + marco-mag.c + +marco_grayscale_SOURCES= \ + marco-grayscale.c + +bin_PROGRAMS=marco-message marco-window-demo + +## cheesy hacks I use, don't really have any business existing. ;-) +noinst_PROGRAMS=marco-mag marco-grayscale + +marco_message_LDADD= @MARCO_MESSAGE_LIBS@ +marco_window_demo_LDADD= @MARCO_WINDOW_DEMO_LIBS@ +marco_mag_LDADD= @MARCO_WINDOW_DEMO_LIBS@ -lm +marco_grayscale_LDADD = @MARCO_WINDOW_DEMO_LIBS@ + +EXTRA_DIST=$(icon_DATA) + diff --git a/src/tools/marco-grayscale.c b/src/tools/marco-grayscale.c new file mode 100644 index 00000000..8d0cd68c --- /dev/null +++ b/src/tools/marco-grayscale.c @@ -0,0 +1,109 @@ +/* Hack for grayscaling an image */ + +/* + * Copyright (C) 2002 Red Hat Inc. + * + * 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 of the + * License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <unistd.h> +#include <stdlib.h> +#include <math.h> + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) + +static GdkPixbuf* +grayscale_pixbuf (GdkPixbuf *pixbuf) +{ + GdkPixbuf *gray; + guchar *pixels; + int rowstride; + int pixstride; + int row; + int n_rows; + int width; + + gray = gdk_pixbuf_copy (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (gray); + pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3; + + pixels = gdk_pixbuf_get_pixels (gray); + n_rows = gdk_pixbuf_get_height (gray); + width = gdk_pixbuf_get_width (gray); + + row = 0; + while (row < n_rows) + { + guchar *p = pixels + row * rowstride; + guchar *end = p + (pixstride * width); + + while (p != end) + { + double v = INTENSITY (p[0], p[1], p[2]); + + p[0] = (guchar) v; + p[1] = (guchar) v; + p[2] = (guchar) v; + + p += pixstride; + } + + ++row; + } + + return gray; +} + +int +main (int argc, char **argv) +{ + GdkPixbuf *pixbuf; + GdkPixbuf *gray; + GError *err; + + if (argc != 2) + { + g_printerr ("specify a single image on the command line\n"); + return 1; + } + + g_type_init (); + + err = NULL; + pixbuf = gdk_pixbuf_new_from_file (argv[1], &err); + if (err != NULL) + { + g_printerr ("failed to load image: %s\n", err->message); + g_error_free (err); + return 1; + } + + gray = grayscale_pixbuf (pixbuf); + + err = NULL; + gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL); + if (err != NULL) + { + g_printerr ("failed to save image: %s\n", err->message); + g_error_free (err); + return 1; + } + + g_print ("wrote grayscale.png\n"); + + return 0; +} diff --git a/src/tools/marco-mag.c b/src/tools/marco-mag.c new file mode 100644 index 00000000..22c7cc3d --- /dev/null +++ b/src/tools/marco-mag.c @@ -0,0 +1,278 @@ +/* Hack for use instead of xmag */ + +/* + * Copyright (C) 2002 Red Hat Inc. + * + * 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 of the + * License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* C99 -- for rint() */ + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <gdk/gdkkeysyms.h> +#include <unistd.h> +#include <stdlib.h> +#include <math.h> + +static GtkWidget *grab_widget = NULL; +static GtkWidget *display_window = NULL; +static int last_grab_x = 0; +static int last_grab_y = 0; +static int last_grab_width = 150; +static int last_grab_height = 150; +static GtkAllocation last_grab_allocation; +static double width_factor = 4.0; +static double height_factor = 4.0; +static GdkInterpType interp_mode = GDK_INTERP_NEAREST; +static guint regrab_idle_id = 0; + +static GdkPixbuf* +get_pixbuf (void) +{ + GdkPixbuf *screenshot; + GdkPixbuf *magnified; + +#if 0 + g_print ("Size %d x %d\n", + last_grab_width, last_grab_height); +#endif + + screenshot = gdk_pixbuf_get_from_drawable (NULL, gdk_get_default_root_window (), + NULL, + last_grab_x, last_grab_y, 0, 0, + last_grab_width, last_grab_height); + + if (screenshot == NULL) + { + g_printerr ("Screenshot failed\n"); + exit (1); + } + + magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor, + last_grab_height * height_factor, + interp_mode); + + + g_object_unref (G_OBJECT (screenshot)); + + return magnified; +} + +static gboolean +regrab_idle (GtkWidget *image) +{ + GdkPixbuf *magnified; + GtkAllocation allocation; + + gtk_widget_get_allocation (image, &allocation); + + if (allocation.width != last_grab_allocation.width || + allocation.height != last_grab_allocation.height) + { + last_grab_width = rint (allocation.width / width_factor); + last_grab_height = rint (allocation.height / height_factor); + last_grab_allocation = allocation; + + magnified = get_pixbuf (); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified); + + g_object_unref (G_OBJECT (magnified)); + } + + regrab_idle_id = 0; + + return FALSE; +} + +static void +image_resized (GtkWidget *image) +{ + if (regrab_idle_id == 0) + regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle, + image, NULL); +} + +static void +grab_area_at_mouse (GtkWidget *invisible, + int x_root, + int y_root) +{ + GdkPixbuf *magnified; + int width, height; + GtkWidget *widget; + + width = last_grab_width; + height = last_grab_height; + + last_grab_x = x_root; + last_grab_y = y_root; + last_grab_width = width; + last_grab_height = height; + + magnified = get_pixbuf (); + + display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (display_window), + last_grab_width, last_grab_height); + widget = gtk_image_new_from_pixbuf (magnified); + gtk_widget_set_size_request (widget, 40, 40); + gtk_container_add (GTK_CONTAINER (display_window), widget); + g_object_unref (G_OBJECT (magnified)); + + g_object_add_weak_pointer (G_OBJECT (display_window), + (gpointer) &display_window); + + g_signal_connect (G_OBJECT (display_window), "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL); + + gtk_widget_show_all (display_window); +} + +static void +shutdown_grab (void) +{ + gdk_keyboard_ungrab (gtk_get_current_event_time ()); + gdk_pointer_ungrab (gtk_get_current_event_time ()); + gtk_grab_remove (grab_widget); +} + +static void +mouse_motion (GtkWidget *invisible, + GdkEventMotion *event, + gpointer data) +{ + +} + +static gboolean +mouse_release (GtkWidget *invisible, + GdkEventButton *event, + gpointer data) +{ + if (event->button != 1) + return FALSE; + + grab_area_at_mouse (invisible, event->x_root, event->y_root); + + shutdown_grab (); + + g_signal_handlers_disconnect_by_func (invisible, mouse_motion, NULL); + g_signal_handlers_disconnect_by_func (invisible, mouse_release, NULL); + + return TRUE; +} + +/* Helper Functions */ + +static gboolean mouse_press (GtkWidget *invisible, + GdkEventButton *event, + gpointer data); + +static gboolean +key_press (GtkWidget *invisible, + GdkEventKey *event, + gpointer data) +{ + if (event->keyval == GDK_Escape) + { + shutdown_grab (); + + g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL); + g_signal_handlers_disconnect_by_func (invisible, key_press, NULL); + + return TRUE; + } + + return FALSE; +} + +static gboolean +mouse_press (GtkWidget *invisible, + GdkEventButton *event, + gpointer data) +{ + if (event->type == GDK_BUTTON_PRESS && + event->button == 1) + { + g_signal_connect (invisible, "motion_notify_event", + G_CALLBACK (mouse_motion), NULL); + g_signal_connect (invisible, "button_release_event", + G_CALLBACK (mouse_release), NULL); + g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL); + g_signal_handlers_disconnect_by_func (invisible, key_press, NULL); + return TRUE; + } + + return FALSE; +} + +static void +begin_area_grab (void) +{ + if (grab_widget == NULL) + { + grab_widget = gtk_invisible_new (); + + gtk_widget_add_events (grab_widget, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + + gtk_widget_show (grab_widget); + } + + if (gdk_keyboard_grab (gtk_widget_get_window (grab_widget), + FALSE, + gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) + { + g_warning ("Failed to grab keyboard to do eyedropper"); + return; + } + + if (gdk_pointer_grab (gtk_widget_get_window (grab_widget), + FALSE, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, + NULL, + NULL, + gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) + { + gdk_keyboard_ungrab (GDK_CURRENT_TIME); + g_warning ("Failed to grab pointer to do eyedropper"); + return; + } + + gtk_grab_add (grab_widget); + + g_signal_connect (grab_widget, "button_press_event", + G_CALLBACK (mouse_press), NULL); + g_signal_connect (grab_widget, "key_press_event", + G_CALLBACK (key_press), NULL); +} + +int +main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + begin_area_grab (); + + gtk_main (); + + return 0; +} diff --git a/src/tools/marco-message.c b/src/tools/marco-message.c new file mode 100644 index 00000000..78bebeb2 --- /dev/null +++ b/src/tools/marco-message.c @@ -0,0 +1,187 @@ +/* Marco send-magic-messages app */ + +/* + * Copyright (C) 2002 Havoc Pennington + * + * 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 of the + * License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <stdlib.h> +#include <string.h> + +#include <libintl.h> +#define _(x) dgettext (GETTEXT_PACKAGE, x) +#define N_(x) x + + +static void +send_restart (void) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + xev.xclient.window = gdk_x11_get_default_root_xwindow (); + xev.xclient.message_type = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + "_MARCO_RESTART_MESSAGE", + False); + xev.xclient.format = 32; + xev.xclient.data.l[0] = 0; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + gdk_x11_get_default_root_xwindow (), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), False); +} + +static void +send_reload_theme (void) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + xev.xclient.window = gdk_x11_get_default_root_xwindow (); + xev.xclient.message_type = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + "_MARCO_RELOAD_THEME_MESSAGE", + False); + xev.xclient.format = 32; + xev.xclient.data.l[0] = 0; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + gdk_x11_get_default_root_xwindow (), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), False); +} + +static void +send_set_keybindings (gboolean enabled) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + xev.xclient.window = gdk_x11_get_default_root_xwindow (); + xev.xclient.message_type = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + "_MARCO_SET_KEYBINDINGS_MESSAGE", + False); + xev.xclient.format = 32; + xev.xclient.data.l[0] = enabled; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + gdk_x11_get_default_root_xwindow (), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), False); +} + +#ifdef WITH_VERBOSE_MODE +static void +send_toggle_verbose (void) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + xev.xclient.window = gdk_x11_get_default_root_xwindow (); + xev.xclient.message_type = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + "_MARCO_TOGGLE_VERBOSE", + False); + xev.xclient.format = 32; + xev.xclient.data.l[0] = 0; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + gdk_x11_get_default_root_xwindow (), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), False); +} +#endif + +static void +usage (void) +{ + g_printerr (_("Usage: %s\n"), + "marco-message (restart|reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)"); + exit (1); +} + +int +main (int argc, char **argv) +{ + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + gtk_init (&argc, &argv); + + if (argc < 2) + usage (); + + if (strcmp (argv[1], "restart") == 0) + send_restart (); + else if (strcmp (argv[1], "reload-theme") == 0) + send_reload_theme (); + else if (strcmp (argv[1], "enable-keybindings") == 0) + send_set_keybindings (TRUE); + else if (strcmp (argv[1], "disable-keybindings") == 0) + send_set_keybindings (FALSE); + else if (strcmp (argv[1], "toggle-verbose") == 0) + { +#ifndef WITH_VERBOSE_MODE + g_printerr (_("Marco was compiled without support for verbose mode\n")); + return 1; +#else + send_toggle_verbose (); +#endif + } + else + usage (); + + return 0; +} + diff --git a/src/tools/marco-window-demo.c b/src/tools/marco-window-demo.c new file mode 100644 index 00000000..876a2585 --- /dev/null +++ b/src/tools/marco-window-demo.c @@ -0,0 +1,1016 @@ +/* Marco window types/properties demo app */ + +/* + * Copyright (C) 2002 Havoc Pennington + * + * 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 of the + * License, 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <X11/Xatom.h> +#include <unistd.h> + +static GtkWidget* do_appwindow (void); + +static gboolean aspect_on; + +static void +set_gdk_window_struts (GdkWindow *window, + int left, + int right, + int top, + int bottom) +{ + long vals[12]; + + vals[0] = left; + vals[1] = right; + vals[2] = top; + vals[3] = bottom; + vals[4] = 000; + vals[5] = 400; + vals[6] = 200; + vals[7] = 600; + vals[8] = 76; + vals[9] = 676; + vals[10] = 200; + vals[11] = 800; + + XChangeProperty (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XWINDOW (window), + XInternAtom (GDK_WINDOW_XDISPLAY (window), + "_NET_WM_STRUT_PARTIAL", False), + XA_CARDINAL, 32, PropModeReplace, + (guchar *)vals, 12); +} + +static void +on_realize_set_struts (GtkWindow *window, + gpointer data) +{ + int left; + int right; + int top; + int bottom; + + g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window))); + + left = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-left")); + right = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-right")); + top = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-top")); + bottom = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-bottom")); + + set_gdk_window_struts (gtk_widget_get_window (GTK_WIDGET (window)), + left, right, top, bottom); +} + +static void +set_gtk_window_struts (GtkWidget *window, + int left, + int right, + int top, + int bottom) +{ + g_object_set_data (G_OBJECT (window), "meta-strut-left", + GINT_TO_POINTER (left)); + g_object_set_data (G_OBJECT (window), "meta-strut-right", + GINT_TO_POINTER (right)); + g_object_set_data (G_OBJECT (window), "meta-strut-top", + GINT_TO_POINTER (top)); + g_object_set_data (G_OBJECT (window), "meta-strut-bottom", + GINT_TO_POINTER (bottom)); + + g_signal_handlers_disconnect_by_func (G_OBJECT (window), + on_realize_set_struts, + NULL); + + g_signal_connect_after (G_OBJECT (window), + "realize", + G_CALLBACK (on_realize_set_struts), + NULL); + + if (gtk_widget_get_realized (GTK_WIDGET (window))) + set_gdk_window_struts (gtk_widget_get_window (GTK_WIDGET (window)), + left, right, top, bottom); +} + +static void +set_gdk_window_type (GdkWindow *window, + const char *type) +{ + Atom atoms[2] = { None, None }; + + atoms[0] = XInternAtom (GDK_WINDOW_XDISPLAY (window), + type, False); + + XChangeProperty (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XWINDOW (window), + XInternAtom (GDK_WINDOW_XDISPLAY (window), "_NET_WM_WINDOW_TYPE", False), + XA_ATOM, 32, PropModeReplace, + (guchar *)atoms, + 1); +} + +static void +on_realize_set_type (GtkWindow *window, + gpointer data) +{ + const char *type; + + g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window))); + + type = g_object_get_data (G_OBJECT (window), "meta-window-type"); + + g_return_if_fail (type != NULL); + + set_gdk_window_type (gtk_widget_get_window (GTK_WIDGET (window)), + type); +} + +static void +set_gtk_window_type (GtkWindow *window, + const char *type) +{ + g_object_set_data (G_OBJECT (window), "meta-window-type", (char*) type); + + g_signal_handlers_disconnect_by_func (G_OBJECT (window), + on_realize_set_type, + NULL); + + g_signal_connect_after (G_OBJECT (window), + "realize", + G_CALLBACK (on_realize_set_type), + NULL); + + if (gtk_widget_get_realized (GTK_WIDGET (window))) + set_gdk_window_type (gtk_widget_get_window (GTK_WIDGET (window)), + type); +} + +static void +set_gdk_window_border_only (GdkWindow *window) +{ + gdk_window_set_decorations (window, GDK_DECOR_BORDER); +} + +static void +on_realize_set_border_only (GtkWindow *window, + gpointer data) +{ + g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window))); + + set_gdk_window_border_only (gtk_widget_get_window (GTK_WIDGET (window))); +} + +static void +set_gtk_window_border_only (GtkWindow *window) +{ + g_signal_handlers_disconnect_by_func (G_OBJECT (window), + on_realize_set_border_only, + NULL); + + g_signal_connect_after (G_OBJECT (window), + "realize", + G_CALLBACK (on_realize_set_border_only), + NULL); + + if (gtk_widget_get_realized (GTK_WIDGET (window))) + set_gdk_window_border_only (gtk_widget_get_window (GTK_WIDGET (window))); +} + +int +main (int argc, char **argv) +{ + GList *list; + GdkPixbuf *pixbuf; + GError *err; + + gtk_init (&argc, &argv); + + err = NULL; + pixbuf = gdk_pixbuf_new_from_file (MARCO_ICON_DIR"/marco-window-demo.png", + &err); + if (pixbuf) + { + list = g_list_prepend (NULL, pixbuf); + + gtk_window_set_default_icon_list (list); + g_list_free (list); + g_object_unref (G_OBJECT (pixbuf)); + } + else + { + g_printerr ("Could not load icon: %s\n", err->message); + g_error_free (err); + } + + do_appwindow (); + + gtk_main (); + + return 0; +} + +static void +response_cb (GtkDialog *dialog, + int response_id, + void *data); + +static void +make_dialog (GtkWidget *parent, + int depth) +{ + GtkWidget *dialog; + char *str; + + dialog = gtk_message_dialog_new (parent ? GTK_WINDOW (parent) : NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + parent ? "Here is a dialog %d" : + "Here is a dialog %d with no transient parent", + depth); + + str = g_strdup_printf ("%d dialog", depth); + gtk_window_set_title (GTK_WINDOW (dialog), str); + g_free (str); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + "Open child dialog", + GTK_RESPONSE_ACCEPT); + + /* Close dialog on user response */ + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (response_cb), + NULL); + + g_object_set_data (G_OBJECT (dialog), "depth", + GINT_TO_POINTER (depth)); + + gtk_widget_show (dialog); +} + +static void +response_cb (GtkDialog *dialog, + int response_id, + void *data) +{ + switch (response_id) + { + case GTK_RESPONSE_ACCEPT: + make_dialog (GTK_WIDGET (dialog), + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), + "depth")) + 1); + break; + + default: + gtk_widget_destroy (GTK_WIDGET (dialog)); + break; + } +} + +static void +dialog_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + make_dialog (GTK_WIDGET (callback_data), 1); +} + +static void +modal_dialog_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (callback_data), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + "Here is a MODAL dialog"); + + set_gtk_window_type (GTK_WINDOW (dialog), "_NET_WM_WINDOW_TYPE_MODAL_DIALOG"); + + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); +} + +static void +no_parent_dialog_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + make_dialog (NULL, 1); +} + +static void +utility_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *button; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_UTILITY"); + gtk_window_set_title (GTK_WINDOW (window), "Utility"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + button = gtk_button_new_with_mnemonic ("_A button"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + button = gtk_button_new_with_mnemonic ("_B button"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + button = gtk_button_new_with_mnemonic ("_C button"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + button = gtk_button_new_with_mnemonic ("_D button"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +static void +toolbar_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_TOOLBAR"); + gtk_window_set_title (GTK_WINDOW (window), "Toolbar"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("FIXME this needs a resize grip, etc."); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +static void +menu_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_MENU"); + gtk_window_set_title (GTK_WINDOW (window), "Menu"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("FIXME this isn't a menu."); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +static void +override_redirect_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_title (GTK_WINDOW (window), "Override Redirect"); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("This is an override\nredirect window\nand should not be managed"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +static void +border_only_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_border_only (GTK_WINDOW (window)); + gtk_window_set_title (GTK_WINDOW (window), "Border only"); + + gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("This window is supposed to have a border but no titlebar."); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} + +#if 0 +static void +changing_icon_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Changing Icon"); + + vbox = gtk_vbox_new (FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + label = gtk_label_new ("This window has an icon that changes over time"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + gtk_widget_show_all (window); +} +#endif + +static gboolean +focus_in_event_cb (GtkWidget *window, + GdkEvent *event, + gpointer data) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (data); + + gtk_label_set_text (GTK_LABEL (widget), "Has focus"); + + return TRUE; +} + + +static gboolean +focus_out_event_cb (GtkWidget *window, + GdkEvent *event, + gpointer data) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (data); + + gtk_label_set_text (GTK_LABEL (widget), "Not focused"); + + return TRUE; +} + +static GtkWidget* +focus_label (GtkWidget *window) +{ + GtkWidget *label; + + label = gtk_label_new ("Not focused"); + + g_signal_connect (G_OBJECT (window), "focus_in_event", + G_CALLBACK (focus_in_event_cb), label); + + g_signal_connect (G_OBJECT (window), "focus_out_event", + G_CALLBACK (focus_out_event_cb), label); + + return label; +} + +static void +splashscreen_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *image; + GtkWidget *vbox; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_SPLASHSCREEN"); + gtk_window_set_title (GTK_WINDOW (window), "Splashscreen"); + + vbox = gtk_vbox_new (FALSE, 0); + + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), focus_label (window), FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + gtk_widget_show_all (window); +} + +enum +{ + DOCK_TOP = 1, + DOCK_BOTTOM = 2, + DOCK_LEFT = 3, + DOCK_RIGHT = 4, + DOCK_ALL = 5 +}; + +static void +make_dock (int type) +{ + GtkWidget *window; + GtkWidget *image; + GtkWidget *box; + GtkWidget *button; + + g_return_if_fail (type != DOCK_ALL); + + box = NULL; + switch (type) + { + case DOCK_LEFT: + case DOCK_RIGHT: + box = gtk_vbox_new (FALSE, 0); + break; + case DOCK_TOP: + case DOCK_BOTTOM: + box = gtk_hbox_new (FALSE, 0); + break; + case DOCK_ALL: + break; + } + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DOCK"); + + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (box), focus_label (window), FALSE, FALSE, 0); + + button = gtk_button_new_with_label ("Close"); + gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); + + g_signal_connect_swapped (G_OBJECT (button), "clicked", + G_CALLBACK (gtk_widget_destroy), window); + + gtk_container_add (GTK_CONTAINER (window), box); + +#define DOCK_SIZE 48 + switch (type) + { + case DOCK_LEFT: + gtk_widget_set_size_request (window, DOCK_SIZE, 400); + gtk_window_move (GTK_WINDOW (window), 0, 000); + set_gtk_window_struts (window, DOCK_SIZE, 0, 0, 0); + gtk_window_set_title (GTK_WINDOW (window), "LeftDock"); + break; + case DOCK_RIGHT: + gtk_widget_set_size_request (window, DOCK_SIZE, 400); + gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 200); + set_gtk_window_struts (window, 0, DOCK_SIZE, 0, 0); + gtk_window_set_title (GTK_WINDOW (window), "RightDock"); + break; + case DOCK_TOP: + gtk_widget_set_size_request (window, 600, DOCK_SIZE); + gtk_window_move (GTK_WINDOW (window), 76, 0); + set_gtk_window_struts (window, 0, 0, DOCK_SIZE, 0); + gtk_window_set_title (GTK_WINDOW (window), "TopDock"); + break; + case DOCK_BOTTOM: + gtk_widget_set_size_request (window, 600, DOCK_SIZE); + gtk_window_move (GTK_WINDOW (window), 200, gdk_screen_height () - DOCK_SIZE); + set_gtk_window_struts (window, 0, 0, 0, DOCK_SIZE); + gtk_window_set_title (GTK_WINDOW (window), "BottomDock"); + break; + case DOCK_ALL: + break; + } + + gtk_widget_show_all (window); +} + +static void +dock_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + if (callback_action == DOCK_ALL) + { + make_dock (DOCK_TOP); + make_dock (DOCK_BOTTOM); + make_dock (DOCK_LEFT); + make_dock (DOCK_RIGHT); + } + else + { + make_dock (callback_action); + } +} + +static void +desktop_cb (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + GtkWidget *window; + GtkWidget *label; + GdkColor desktop_color; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DESKTOP"); + gtk_window_set_title (GTK_WINDOW (window), "Desktop"); + gtk_widget_set_size_request (window, + gdk_screen_width (), gdk_screen_height ()); + gtk_window_move (GTK_WINDOW (window), 0, 0); + + desktop_color.red = 0x5144; + desktop_color.green = 0x75D6; + desktop_color.blue = 0xA699; + + gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &desktop_color); + + label = focus_label (window); + + gtk_container_add (GTK_CONTAINER (window), label); + + gtk_widget_show_all (window); +} + +static GtkItemFactoryEntry menu_items[] = +{ + { "/_Windows", NULL, NULL, 0, "<Branch>" }, + { "/Windows/tearoff", NULL, NULL, 0, "<Tearoff>" }, + { "/Windows/_Dialog", "<control>d", dialog_cb, 0, NULL }, + { "/Windows/_Modal dialog", NULL, modal_dialog_cb, 0, NULL }, + { "/Windows/_Parentless dialog", NULL, no_parent_dialog_cb, 0, NULL }, + { "/Windows/_Utility", "<control>u", utility_cb, 0, NULL }, + { "/Windows/_Splashscreen", "<control>s", splashscreen_cb, 0, NULL }, + { "/Windows/_Top dock", NULL, dock_cb, DOCK_TOP, NULL }, + { "/Windows/_Bottom dock", NULL, dock_cb, DOCK_BOTTOM, NULL }, + { "/Windows/_Left dock", NULL, dock_cb, DOCK_LEFT, NULL }, + { "/Windows/_Right dock", NULL, dock_cb, DOCK_RIGHT, NULL }, + { "/Windows/_All docks", NULL, dock_cb, DOCK_ALL, NULL }, + { "/Windows/Des_ktop", NULL, desktop_cb, 0, NULL }, + { "/Windows/Me_nu", NULL, menu_cb, 0, NULL }, + { "/Windows/Tool_bar", NULL, toolbar_cb, 0, NULL }, + { "/Windows/Override Redirect", NULL, override_redirect_cb, 0, NULL }, + { "/Windows/Border Only", NULL, border_only_cb, 0, NULL } +}; + +static void +sleep_cb (GtkWidget *button, + gpointer data) +{ + sleep (1000); +} + +static void +toggle_aspect_ratio (GtkWidget *button, + gpointer data) +{ + GtkWidget *window; + GdkGeometry geom; + + if (aspect_on) + { + geom.min_aspect = 0; + geom.max_aspect = 65535; + } + else + { + geom.min_aspect = 1.777778; + geom.max_aspect = 1.777778; + } + + aspect_on = !aspect_on; + + window = gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW); + if (window) + gtk_window_set_geometry_hints (GTK_WINDOW (window), + GTK_WIDGET (data), + &geom, + GDK_HINT_ASPECT); + +} + +static void +toggle_decorated_cb (GtkWidget *button, + gpointer data) +{ + GtkWidget *window; + window = gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW); + if (window) + gtk_window_set_decorated (GTK_WINDOW (window), + !gtk_window_get_decorated (GTK_WINDOW (window))); +} + +static void +clicked_toolbar_cb (GtkWidget *button, + gpointer data) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (data), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + "Clicking the toolbar buttons doesn't do anything"); + + /* Close dialog on user response */ + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_widget_show (dialog); +} + +static void +update_statusbar (GtkTextBuffer *buffer, + GtkStatusbar *statusbar) +{ + gchar *msg; + gint row, col; + gint count; + GtkTextIter iter; + + gtk_statusbar_pop (statusbar, 0); /* clear any previous message, underflow is allowed */ + + count = gtk_text_buffer_get_char_count (buffer); + + gtk_text_buffer_get_iter_at_mark (buffer, + &iter, + gtk_text_buffer_get_insert (buffer)); + + row = gtk_text_iter_get_line (&iter); + col = gtk_text_iter_get_line_offset (&iter); + + msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document", + row, col, count); + + gtk_statusbar_push (statusbar, 0, msg); + + g_free (msg); +} + +static void +mark_set_callback (GtkTextBuffer *buffer, + const GtkTextIter *new_location, + GtkTextMark *mark, + gpointer data) +{ + update_statusbar (buffer, GTK_STATUSBAR (data)); +} + +static int window_count = 0; + +static void +destroy_cb (GtkWidget *w, gpointer data) +{ + --window_count; + if (window_count == 0) + gtk_main_quit (); +} + +static GtkWidget * +do_appwindow (void) +{ + GtkWidget *window; + GtkWidget *table; + GtkWidget *toolbar; + GtkWidget *handlebox; + GtkWidget *statusbar; + GtkWidget *contents; + GtkWidget *sw; + GtkTextBuffer *buffer; + GtkAccelGroup *accel_group; + GtkItemFactory *item_factory; + + + /* Create the toplevel window + */ + + ++window_count; + + aspect_on = FALSE; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Application Window"); + + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (destroy_cb), NULL); + + table = gtk_table_new (1, 4, FALSE); + + gtk_container_add (GTK_CONTAINER (window), table); + + /* Create the menubar + */ + + accel_group = gtk_accel_group_new (); + gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); + g_object_unref (accel_group); + + item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group); + + /* Set up item factory to go away with the window */ + g_object_ref (item_factory); + g_object_ref_sink (item_factory); + g_object_unref (item_factory); + g_object_set_data_full (G_OBJECT (window), + "<main>", + item_factory, + (GDestroyNotify) g_object_unref); + + /* create menu items */ + gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items), + menu_items, window); + + gtk_table_attach (GTK_TABLE (table), + gtk_item_factory_get_widget (item_factory, "<main>"), + /* X direction */ /* Y direction */ + 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, 0, + 0, 0); + + /* Create document + */ + + sw = gtk_scrolled_window_new (NULL, NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_IN); + + gtk_table_attach (GTK_TABLE (table), + sw, + /* X direction */ /* Y direction */ + 0, 1, 2, 3, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, + 0, 0); + + gtk_window_set_default_size (GTK_WINDOW (window), + 200, 200); + + contents = gtk_text_view_new (); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents), + PANGO_WRAP_WORD); + + gtk_container_add (GTK_CONTAINER (sw), + contents); + + /* Create the toolbar + */ + toolbar = gtk_toolbar_new (); + + GtkToolItem *newButton = gtk_tool_button_new_from_stock(GTK_STOCK_NEW); + gtk_tool_item_set_tooltip_text(newButton, + "Open another one of these windows"); + g_signal_connect(G_OBJECT(newButton), + "clicked", + G_CALLBACK(do_appwindow), + window); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + newButton, + -1); /*-1 means append to end of toolbar*/ + + + GtkToolItem *lockButton = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); + gtk_tool_item_set_tooltip_text(lockButton, + "This is a demo button that locks up the demo"); + g_signal_connect(G_OBJECT(lockButton), + "clicked", + G_CALLBACK(sleep_cb), + window); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + lockButton, + -1); /*-1 means append to end of toolbar*/ + + + GtkToolItem *decoButton = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); + gtk_tool_item_set_tooltip_text(decoButton, + "This is a demo button that toggles window decorations"); + g_signal_connect(G_OBJECT(decoButton), + "clicked", + G_CALLBACK(toggle_decorated_cb), + window); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + decoButton, + -1); /*-1 means append to end of toolbar*/ + + GtkToolItem *lockRatioButton = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); + gtk_tool_item_set_tooltip_text(lockRatioButton, + "This is a demo button that locks the aspect ratio using a hint"); + g_signal_connect(G_OBJECT(lockRatioButton), + "clicked", + G_CALLBACK(toggle_aspect_ratio), + window); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + lockRatioButton, + -1); /*-1 means append to end of toolbar*/ + + GtkToolItem *quitButton = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); + gtk_tool_item_set_tooltip_text(quitButton, + "This is a demo button with a 'quit' icon"); + g_signal_connect(G_OBJECT(quitButton), + "clicked", + G_CALLBACK(clicked_toolbar_cb), + window); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), + quitButton, + -1); /*-1 means append to end of toolbar*/ + + handlebox = gtk_handle_box_new (); + + gtk_container_add (GTK_CONTAINER (handlebox), toolbar); + + gtk_table_attach (GTK_TABLE (table), + handlebox, + /* X direction */ /* Y direction */ + 0, 1, 1, 2, + GTK_EXPAND | GTK_FILL, 0, + 0, 0); + + /* Create statusbar */ + + statusbar = gtk_statusbar_new (); + gtk_table_attach (GTK_TABLE (table), + statusbar, + /* X direction */ /* Y direction */ + 0, 1, 3, 4, + GTK_EXPAND | GTK_FILL, 0, + 0, 0); + + /* Show text widget info in the statusbar */ + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents)); + + gtk_text_buffer_set_text (buffer, + "This demo demonstrates various kinds of windows that " + "window managers and window manager themes should handle. " + "Be sure to tear off the menu and toolbar, those are also " + "a special kind of window.", + -1); + + g_signal_connect_object (buffer, + "changed", + G_CALLBACK (update_statusbar), + statusbar, + 0); + + g_signal_connect_object (buffer, + "mark_set", /* cursor moved */ + G_CALLBACK (mark_set_callback), + statusbar, + 0); + + update_statusbar (buffer, GTK_STATUSBAR (statusbar)); + + gtk_widget_show_all (window); + + return window; +} + + diff --git a/src/tools/marco-window-demo.png b/src/tools/marco-window-demo.png Binary files differnew file mode 100644 index 00000000..d87f8296 --- /dev/null +++ b/src/tools/marco-window-demo.png |