JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
i- A new quirk to accommodate the idiosyncrasies of XEmacs (and maybe
authorMarco Peereboom <marco@conformal.com>
Tue, 3 May 2011 16:46:52 +0000 (16:46 +0000)
committerMarco Peereboom <marco@conformal.com>
Tue, 3 May 2011 16:46:52 +0000 (16:46 +0000)
other programs). When XEmacs causes a ConfigurationRequest to be
generated, it expects the ConfigureNotify response to contain matching
dimensions. If it doesn't get a matching response, it re-sends the
ConfigureRequest forever.

- Don't send ConfigureRequest events to applications using this new
quirk because, at least for XEmacs, they prevent the window contents
from filling the window frame. I also put some comments in the
"configreq_win" function questioning whether it's actually needed. I
think it may be superfluous, given that it's always called right after a
call to "XConfigureWindow". But this assertion is based on my limited
testing and should be reviewed by an actual X protocol expert.

- Apply the existing "floating" quirk to the XEmacs Ediff window, so
that it acts like a dialog box.

- In the "propertynotify" function, call "bar_update" for the XA_WM_NAME
property. This helps for things like shells that update the XTerm title
to reflect the user's current directory.

Some of this may sound familiar. I sent a similar patch a long time ago,
but you wanted some revisions. Two years on, here they are. So much for
quick turnaround.

from Chuck Musser <cmusser@sonic.net>

scrotwm.c

index 01cbd38..6fab546 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -268,6 +268,7 @@ struct ws_win {
        int                     can_delete;
        int                     take_focus;
        int                     java;
+       int                     init_configreq_tweak_done;
        unsigned long           quirks;
        struct workspace        *ws;    /* always valid */
        struct swm_screen       *s;     /* always valid, never changes */
@@ -403,6 +404,10 @@ struct quirk {
 #define SWM_Q_ANYWHERE         (1<<2)  /* don't position this window */
 #define SWM_Q_XTERM_FONTADJ    (1<<3)  /* adjust xterm fonts when resizing */
 #define SWM_Q_FULLSCREEN       (1<<4)  /* remove border */
+#define SWM_Q_HONOR_CONFREQ    (1<<5)  /* Accomodate applications that
+                                          need the dimensions in configuration
+                                          requests to be honored.
+                                       */
 };
 int                            quirks_size = 0, quirks_length = 0;
 struct quirk                   *quirks = NULL;
@@ -1381,7 +1386,14 @@ configreq_win(struct ws_win *win)
 {
        XConfigureRequestEvent  cr;
 
-       if (win == NULL)
+       /* This function may be of dubious value; it is always called
+          immediately after a call to XConfigureWindow, which generates a
+          ConfigureRequestEvent of its own. The event generated here seems
+           redundant and prevents XEmacs from completely filling the window
+           frame. Simply eliminating confreq_win appeared to have no ill
+           effects, but my testing was limited. As such, I've retained it.
+       */
+       if (win == NULL || (win->quirks & SWM_Q_HONOR_CONFREQ))
                return;
 
        bzero(&cr, sizeof cr);
@@ -3816,6 +3828,7 @@ const char *quirkname[] = {
        "ANYWHERE",
        "XTERM_FONTADJ",
        "FULLSCREEN",
+       "HONOR_CONFREQ",
 };
 
 /* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */
@@ -3962,6 +3975,8 @@ setup_quirks(void)
        setquirk("Xitk",                "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE);
        setquirk("xine",                "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT);
        setquirk("pcb",                 "pcb",          SWM_Q_FLOAT);
+       setquirk("Emacs",               "emacs",        SWM_Q_HONOR_CONFREQ);
+       setquirk("Emacs",               "Ediff",        SWM_Q_FLOAT);
 }
 
 /* conf file stuff */
@@ -4352,6 +4367,7 @@ manage_window(Window id)
        win->g_floatvalid = 0;
        win->floatmaxed = 0;
        win->ewmh_flags = 0;
+       win->init_configreq_tweak_done = 0;
 
        /* Set window properties so we can remember this after reincarnation */
        if (ws_idx_atom && prop == NULL &&
@@ -4585,6 +4601,55 @@ buttonpress(XEvent *e)
                        buttons[i].func(win, &buttons[i].args);
 }
 
+/*
+ * honor_configreq:    allow fussy windows to work in scrotwm
+ *
+ *     XEmacs (and maybe other applications) expects ConfigureNotify
+ *     events that exactly match the ConfigureRequests that it generates.
+ *     Because Scrotwm specifies both the location *and* size of new
+ *     windows, these applications will not be satisfied and will repeat
+ *     the request forever. This bogs down the system and makes the
+ *     application unusable.
+ *
+ *     To resolve this conflict, this function responds to ConfigureRequest
+ *     by sending a ConfigureNotify that contains the requested dimensions.
+ *     It then resizes the window to the dimensions computed by scrotwm.
+ *     And then it gets stranger still: after the initial response, the
+ *     height stored in window manager's dimensions needs to be different
+ *     than the value initially computed. If it's not, the window contents
+ *     aren't resized to fill the frame.
+ *
+ */
+void honor_configreq (
+       struct ws_win*          win,
+       XConfigureRequestEvent* ev
+    )
+{
+       XConfigureEvent         ce;
+
+       ce.type                 = ConfigureNotify;
+       ce.display              = ev->display;
+       ce.event                = ev->window;
+       ce.window               = ev->window;
+       ce.x                    = ev->x;
+       ce.y                    = ev->y;
+       ce.width                = ev->width;
+       ce.height               = ev->height;
+       ce.border_width         = ev->border_width;
+       ce.above                = ev->above;
+       ce.override_redirect    = False;
+
+       XSendEvent(ev->display, ev->window, False, StructureNotifyMask,
+                  (XEvent *)&ce);
+
+       XResizeWindow(display, ev->window, win->g.w, win->g.h);
+
+       if (win->init_configreq_tweak_done == 0) {
+               win->init_configreq_tweak_done = 1;
+               win->g.h--;
+       }
+}
+
 void
 configurerequest(XEvent *e)
 {
@@ -4621,8 +4686,12 @@ configurerequest(XEvent *e)
                                win->g.w = ev->width;
                        if (ev->value_mask & CWHeight)
                                win->g.h = ev->height;
+                       config_win(win);
+               } else if (win->quirks & SWM_Q_HONOR_CONFREQ) {
+                       honor_configreq(win, ev);
+               } else {
+                       config_win(win);
                }
-               config_win(win);
        }
 }
 
@@ -4913,6 +4982,10 @@ propertynotify(XEvent *e)
                if (window_name_enabled)
                        bar_update();
                break;
+       case XA_WM_NAME:
+               /* Be responsive to clients that change the application name. */
+               bar_update();
+               break;
        default:
                break;
        }