Patch for modal windows, and more.
- From: Elliot Lee <sopwith redhat com>
- To: gtk-list redhat com
- Subject: Patch for modal windows, and more.
- Date: Fri, 4 Jul 1997 16:03:34 -0400 (EDT)
This is a rather crude hack to try get the ball rolling with modal
dialogs. It will drive you crazy if you have your WM in FocusFollowsMouse
mode, but the point of it is to make sure the modal window always has
focus.
Please take this and add features on to it so eventually this
wonderful-and-perfect modal dialog box patch will evolve. I think the next
logical step would be to find a way to make it so that the WM never
removes focus from the window if the focusout is going to another window
for the client. Perhaps also filter out all mouse events so they don't go
to other windows of the client while a modal is popped up.
Also, if anyone wants to play with drag and drop, try out
ftp://ftp.redhat.com/sopwith/gtk-xde5.patch.gz please - it is more or less
how I think D&D should be done, it's not hard to add D&D to existing gtk
apps (and I hope to add some D&D to the main gtk widgets sometime).
Hope this helps,
-- "hacking gtk to bits" Elliot
--- gimp-0.99.10/gtk+/gdk/gdkwindow.c.sopwith Fri Jul 4 12:17:35 1997
+++ gimp-0.99.10/gtk+/gdk/gdkwindow.c Fri Jul 4 15:49:42 1997
@@ -207,6 +207,8 @@
switch (private->window_type)
{
+ case GDK_WINDOW_DIALOG_MODAL:
+ gdk_window_modal_push(window);
case GDK_WINDOW_DIALOG:
XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
case GDK_WINDOW_TOPLEVEL:
@@ -272,6 +274,8 @@
switch (private->window_type)
{
+ case GDK_WINDOW_DIALOG_MODAL:
+ gdk_window_modal_pop(window);
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
@@ -959,4 +963,26 @@
g_free (new_windows);
if (old_windows)
XFree (old_windows);
+}
+
+void
+gdk_window_modal_push(GdkWindow *window)
+{
+ g_return_if_fail(window != NULL);
+ g_return_if_fail(((GdkWindowPrivate *)window)->window_type
+ == GDK_WINDOW_DIALOG_MODAL);
+ g_return_if_fail(gdk_modals_stack->data != (gpointer)window);
+ gdk_modals_stack = g_slist_prepend(gdk_modals_stack, (gpointer) window);
+}
+
+void
+gdk_window_modal_pop(GdkWindow *window)
+{
+ GSList *tmp = gdk_modals_stack;
+
+ g_return_if_fail((gpointer)window == tmp->data);
+
+ gdk_modals_stack = g_slist_remove_link(gdk_modals_stack,
+ gdk_modals_stack);
+ g_slist_free(tmp);
}
--- gimp-0.99.10/gtk+/gdk/gdk.c.sopwith Fri Jul 4 12:22:19 1997
+++ gimp-0.99.10/gtk+/gdk/gdk.c Fri Jul 4 15:47:52 1997
@@ -307,6 +307,8 @@
gdk_wm_window_protocols[1] = gdk_wm_take_focus;
gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
+ gdk_modals_stack = g_slist_alloc();
+
XGetKeyboardControl (gdk_display, &keyboard_state);
autorepeat = keyboard_state.global_auto_repeat;
@@ -1746,13 +1748,35 @@
}
else if (xevent->xclient.data.l[0] == gdk_wm_take_focus)
{
+ /* We use this for modal dialogs */
+
/* Print debugging info.
*/
if (gdk_show_events)
g_print ("take focus:\t\twindow: %ld\n",
xevent->xclient.window - base_id);
- /* Not currently handled */
+ if(gdk_modals_stack->data != NULL
+ && gdk_modals_stack->data != (gpointer)window) {
+ /* We want to refocus on our modal window */
+ XRaiseWindow(gdk_display,
+ ((GdkWindowPrivate *)
+ gdk_modals_stack->data)->xwindow);
+ XBell(gdk_display, 0); /* XXX do we need this? */
+ XSetInputFocus(gdk_display,
+ ((GdkWindowPrivate *)
+ gdk_modals_stack->data)->xwindow,
+ RevertToPointerRoot, xevent->xclient.data.l[1]);
+ g_print("Set focus on %ld\n",
+ ((GdkWindowPrivate *)
+ gdk_modals_stack->data)->xwindow);
+#ifndef NDEBUG
+ } else {
+ if(gdk_show_events)
+ g_print("Window %ld can keep focus\n",
+ xevent->xfocus.window - base_id);
+ }
+#endif
}
}
break;
--- gimp-0.99.10/gtk+/gdk/gdkglobals.c.sopwith Fri Jul 4 12:22:21 1997
+++ gimp-0.99.10/gtk+/gdk/gdkglobals.c Fri Jul 4 14:30:51 1997
@@ -21,7 +21,7 @@
#include "gdkprivate.h"
gint gdk_debug_level = 0;
-gint gdk_show_events = FALSE;
+gint gdk_show_events = TRUE;
gint gdk_use_xshm = TRUE;
gchar *gdk_display_name = NULL;
Display *gdk_display = NULL;
@@ -37,3 +37,4 @@
gchar *gdk_progname = NULL;
gint gdk_error_code;
gint gdk_error_warnings = TRUE;
+GSList *gdk_modals_stack = NULL;
--- gimp-0.99.10/gtk+/gdk/gdkprivate.h.sopwith Fri Jul 4 12:22:25 1997
+++ gimp-0.99.10/gtk+/gdk/gdkprivate.h Fri Jul 4 12:43:08 1997
@@ -152,6 +152,7 @@
extern gchar *gdk_progname;
extern gint gdk_error_code;
extern gint gdk_error_warnings;
+extern GSList *gdk_modals_stack;
#ifdef __cplusplus
--- gimp-0.99.10/gtk+/gdk/gdk.h.sopwith Fri Jul 4 12:32:18 1997
+++ gimp-0.99.10/gtk+/gdk/gdk.h Fri Jul 4 15:16:55 1997
@@ -182,6 +182,8 @@
GdkWindow* gdk_window_get_parent (GdkWindow *window);
GdkWindow* gdk_window_get_toplevel (GdkWindow *window);
GList* gdk_window_get_children (GdkWindow *window);
+void gdk_window_modal_push (GdkWindow *window);
+void gdk_window_modal_pop (GdkWindow *window);
/* Cursors
--- gimp-0.99.10/gtk+/gtk/gtkwindow.c.sopwith Fri Jul 4 14:03:26 1997
+++ gimp-0.99.10/gtk+/gtk/gtkwindow.c Fri Jul 4 14:04:10 1997
@@ -456,6 +456,9 @@
case GTK_WINDOW_DIALOG:
attributes.window_type = GDK_WINDOW_DIALOG;
break;
+ case GTK_WINDOW_DIALOG_MODAL:
+ attributes.window_type = GDK_WINDOW_DIALOG_MODAL;
+ break;
case GTK_WINDOW_POPUP:
attributes.window_type = GDK_WINDOW_TEMP;
break;
--- gimp-0.99.10/gtk+/gtk/gtkenums.h.sopwith Fri Jul 4 13:45:21 1997
+++ gimp-0.99.10/gtk+/gtk/gtkenums.h Fri Jul 4 14:11:06 1997
@@ -54,7 +54,8 @@
{
GTK_WINDOW_TOPLEVEL,
GTK_WINDOW_DIALOG,
- GTK_WINDOW_POPUP
+ GTK_WINDOW_POPUP,
+ GTK_WINDOW_DIALOG_MODAL
} GtkWindowType;
/* Focus movement types */
--- gimp-0.99.10/gtk+/gtk/testgtk.c.sopwith Fri Jul 4 14:25:28 1997
+++ gimp-0.99.10/gtk+/gtk/testgtk.c Fri Jul 4 14:25:41 1997
@@ -49,7 +49,7 @@
if (!window)
{
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ window = gtk_window_new (GTK_WINDOW_DIALOG_MODAL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
(GtkSignalFunc) destroy_window,
&window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]