chjj / compton

A compositor for X11.
Other
2.25k stars 500 forks source link

fvwm + firefox some dialogs doesn't showup #5

Closed bigsun closed 12 years ago

bigsun commented 12 years ago

I have used compton for a time. recently, I found a problem. When I choose savePageAs or savePictureAs, the dialog window didn't show, it was under the main window. this was also found when using stardict(choose preference from menu). can you resolve it for fvwm users.

chjj commented 12 years ago

What do you mean by under the main window? Compton does not change window behavior/position at all, it only paints the screen differently.

Also, what options were you running compton with?

bigsun commented 12 years ago

I mean the browser window(main window) is on top of the new opened dialog window(subwindow), so the dialog can't be seen. I switch back to xcompmgr, the problem doesn't occur. I start compton with the command: compton -cCfF -r5 -o.8 -D1, and when I start compton without any parameter, the result is the same.

japrogramer commented 12 years ago

this happens to me with gimp, i don't know if it is because i use xmonad and have a custom layout for gimp but i don't think that should be a problem because the dialogue box in question i have to float and only occasionally occurs in other windows note in my experience it doesn't change the windowing order it only seems to draw it as if it was underneath but it really isin't if you want i can do a screencast demonstrating the problem

chjj commented 12 years ago

Could you show me the output of xprop | grep _NET_WM_WINDOW_TYPE after you select the window(s) in question (without compton running)?

A video or a screenshot would be very helpful too.

edit: Also, does this same problem occur with the original xcompmgr?

japrogramer commented 12 years ago

_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG

bigsun commented 12 years ago

same as japrogramer: _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG

my screencast: https://github.com/bigsun/mycapture

chjj commented 12 years ago

I watched your video. I saw a Save dialog pop up and then it looked like it was closed. Was it not supposed to disappear like that? (I couldn't tell whether you clicked something or not). Anyway, if that is what it is, I'll see what I can do.

bigsun commented 12 years ago

at the first time, I have closed the save dialog. at the second time, save dialog seems under the main browser window, I must switch to it or click anywhere on browser window to show the dialog.

richardgv commented 12 years ago

Exactly the same problem here. I'm still not certain in how this problem is triggered, but it seems particularly likely to happen when a window not currently focused or partially overlapped by other windows creates a new transient window -- but it does not always happen in these situations.

I personally launch compton with compton -cCGfFz -m 0.9 -D 30 -O 0.3 -I 0.3 -o 0.5, but even without any switches turned on (compton) the problem still appears.

I found the transient window is drawn correctly after I move the parent window or the window itself, so I used the following workaround in ~/.fvwm/config, to slightly move any newly created windows, then move them back. Definitely an ugly one, though:

AddToFunc StartFunction
+ I Schedule 100 Module FvwmEvent

DestroyFunc func_add_window
AddToFunc   func_add_window
+ I Move w1p w1p
+ I Move w-1p w-1p

*FvwmEvent: Cmd
*FvwmEvent: add_window func_add_window
lswest commented 12 years ago

I've had similar behaviour with xcompmgr as well (any version of it). I use it with a tiling window manager (XMonad) and practically every dialog window is opened underneath the main window. This includes things like creating archives from files using the file manager's (thunar/nautilus) context menu, to the settings dialog windows in Firefox. If you need more information, I'll be happy to supply it.

chjj commented 12 years ago

I found the transient window is drawn correctly after I move the parent window or the window itself, so I used the following workaround in ~/.fvwm/config, to slightly move any newly created windows, then move them back. Definitely an ugly one, though:

Thanks. That's a very nice clue.

I've had similar behaviour with xcompmgr as well (any version of it). I use it with a tiling window manager (XMonad) and practically every dialog window is opened underneath the main window. This includes things like creating archives from files using the file manager's (thunar/nautilus) context menu, to the settings dialog windows in Firefox. If you need more information, I'll be happy to supply it.

The window should never be under the parent window. compton doesn't affect window behavior, only how the windows are drawn to the screen. Anymore info would be great though.

lswest commented 12 years ago

I realize that compton doesn't affect the window behaviour. From what I can figure though, it seems to have an impact on the perceived properties of windows. By this I mean that there is some property that is adjusted which leads to XMonad not applying the right settings to it. I can't say if moving the window will allow the dialog to appear, since the window is usually tiled in front of it. That being said, when floating a window I can clearly see that the dialog appears behind the floated window, and given focus (which should actually raise it as well). I'm not sure how much more information I can supply, besides the fact that I have had this behavious occur with compton/xcompmgr in DWM, AwesomeWM, XMonad and WMFS. Also, it occurs both on my laptop (basic intel integrated graphics) and my PC (with the proprietary nvidia drivers). If someone has a suggestion as to where I should start looking to get more information, I'll be happy to give it a shot.

As for distribution: I've only tested this (recently) in ArchLinux x86_64, with the linux kernel 3.2.14 and 3.3.1, and the latest drivers available for intel and nvidia.

richardgv commented 12 years ago

Yes, the window is actually drawn, it's just behind its parent window. After I resized the parent window to a smaller size I could see the "hidden" window behind the parent window.

Also, it's pretty funny that even though I could not see the window, I could click the buttons in it.

I tried to apply fvwm's Focus command to the "hidden" window, didn't help, the window remains hidden, but "Raise" command works. Switching virtual desktop does not help. Fvwm's 3 options about transient windows, "RaiseTransient, LowerTransient, StackTransientParent", don't seem to have any effect here, either.

Full xprop output of a hidden window: http://pastebin.com/DirexKMM How FvwmIdenti perceives the window: http://dl.dropbox.com/u/283669/stc/fvwmidenti.png

william-s commented 12 years ago

I have the same issue using XMonad. If, for example, when I launch mutt from a transparent term, it launches a GTK window for GPG decrypt. This window is only visible behind the shading of the term background, however text input is still sent to the dialog. Similar windows in other programs that aren't transparent or require mouse interaction are unusable. FWIW I didn't have this problem using xcompmgr.

akrito commented 12 years ago

I experience the same issue while using compton in XMonad with Google Chrome save dialogs - I know a window should show, but I can't see it. However, if I use the mouse to grab and move the area where I suspect there's a popup window, it appears.

chjj commented 12 years ago

This is probably a failure in the order the windows are painted to the buffer. Either that, or the window doesn't get mapped properly in the first place i.e. an event isn't being handled properly. I've been looking at any code that deals with the windows linked list very suspiciously. I'll probably just have to use XMonad myself to debug it.

radiosilence commented 12 years ago

I also get this issue with the save dialogue in Chrome. Anyone got a fix yet?

radiosilence commented 12 years ago

It seems to happen if I right click->save as..., however if I press Ctrl+S, the window spawns as normal.

intervigilium commented 12 years ago

For me this issue occurs whenever there is a new floating window. I'm using Xmonad 0.10-3 under Ubuntu 12.04 with NVIDIA card/drivers.

radiosilence commented 12 years ago

Ok, confirming this happening with almost all floating windows, I'm using Xmonad under Arch Linux with NVIDIA drivers.

richardgv commented 12 years ago

After hours of debugging I guess I found out the problem.

How I reproduce the issue:

  1. You must use MouseFocus/SloppyFocus (basically moving cursor over a window gives it focus, no need to click the window), instead of ClickFocus. That's probably why you didn't notice it on Openbox.
  2. Suppose you have a window A that displays new a transient child window. There needs to be a window B that stacks upon window A -- it doesn't have to overlap window A, it just have to be stacked higher than window A.
  3. Let window A display that transient window. The bug pops up.
  4. I personally just use gVim as window A, let it spawn a child window by clicking "File" -> "Save As". Window B can be a random one.

A brief explaination

After comparing compton's and xcompmgr's calling of restack_win(), I found when the bug appears, compton calls restack_win() one more time, making the window stack incorrect. More specificially, map_win() calls configure_win() if the window need_configure, and configure_win() unconditionally calls restack_win(), generating an extra call to it. xcompmgr does not have this design. I'm not sure why this additional call break things, so there could be a better fix. I'm only able to prevent the extra call. Patch below:

--- src/compton.c   2012-09-07 10:30:08.439925156 +0800
+++ src/compton.new.c   2012-09-07 10:35:17.019922930 +0800
@@ -1712,7 +1712,10 @@
     /* save the configure event for when the window maps */
     w->need_configure = True;
     w->queue_configure = *ce;
+    restack_win(dpy, w, ce->above);
   } else {
+    if (!(w->need_configure))
+      restack_win(dpy, w, ce->above);
     w->need_configure = False;

 #if CAN_DO_USABLE
@@ -1760,7 +1763,6 @@
   }

   w->a.override_redirect = ce->override_redirect;
-  restack_win(dpy, w, ce->above);
 }

 static void

How it was discovered:

My knowledge about Xlib is close to zero, but I managed to add some debugging code to enhance the DEBUG_EVENTS feature. Here's the patch of my debugging code, fixing some little bugs in the original DEBUG_EVENTS code, too:

--- src/compton.c   2012-09-07 11:02:49.389911014 +0800
+++ src/compton.new.c   2012-09-07 10:51:51.689915757 +0800
@@ -10,6 +10,10 @@

 #include "compton.h"

+#if DEBUG_EVENTS
+static int window_get_name(Window w, char **name);
+#endif
+
 /**
  * Shared
  */
@@ -1688,6 +1692,33 @@

     w->next = *prev;
     *prev = w;
+
+#if DEBUG_EVENTS
+    {
+      const char *desc;
+      char *window_name;
+      Bool to_free;
+      win* c = list;
+  
+      printf("restack_win(%#010lx, %#010lx): Window stack modified. Current stack:\n", w->id, new_above);
+      for (; c; c = c->next) {
+        window_name = "(Failed to get title)";
+        if (root == c->id)
+          window_name = "(Root window)";
+        else
+          to_free = window_get_name(c->id, &window_name);
+        desc = "";
+        if (c->destroyed)
+          desc = "(D) ";
+        printf("%#010lx \"%s\" %s-> ", c->id, window_name, desc);
+        if (to_free) {
+          XFree(window_name);
+          window_name = NULL;
+        }
+      }
+      fputs("\n", stdout);
+    }
+#endif
   }
 }

@@ -1965,9 +1996,33 @@
 }

 #if DEBUG_EVENTS
+static int window_get_name(Window w, char **name) {
+  Atom prop = XInternAtom(dpy, "_NET_WM_NAME", False);
+  Atom utf8_type = XInternAtom(dpy, "UTF8_STRING", False);
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems;
+  unsigned long leftover;
+  char *data = NULL;
+  Status ret;
+
+  if (Success != (ret = XGetWindowProperty(dpy, w, prop, 0L, (long) BUFSIZ,
+        False, utf8_type, &actual_type, &actual_format, &nitems,
+        &leftover, (unsigned char **) &data))) {
+    if (BadWindow == ret)
+      return 0;
+    printf("Window %#010lx: _NET_WM_NAME unset, falling back to WM_NAME.\n", w);
+    if (!XFetchName(dpy, w, &data))
+      return 0;
+  }
+  // if (actual_type == utf8_type && actual_format == 8)
+  *name = (char *) data;
+  return 1;
+}
+
 static int
 ev_serial(XEvent *ev) {
-  if (ev->type & 0x7f != KeymapNotify) {
+  if ((ev->type & 0x7f) != KeymapNotify) {
     return ev->xany.serial;
   }
   return NextRequest(ev->xany.display);
@@ -1977,8 +2032,16 @@
 ev_name(XEvent *ev) {
   static char buf[128];
   switch (ev->type & 0x7f) {
-    case Expose:
-      return "Expose";
+    case FocusIn:
+      return "FocusIn";
+    case FocusOut:
+      return "FocusOut";
+    case CreateNotify:
+      return "CreateNotify";
+    case ConfigureNotify:
+      return "ConfigureNotify";
+    case DestroyNotify:
+      return "DestroyNotify";
     case MapNotify:
       return "Map";
     case UnmapNotify:
@@ -1987,6 +2050,10 @@
       return "Reparent";
     case CirculateNotify:
       return "Circulate";
+    case Expose:
+      return "Expose";
+    case PropertyNotify:
+      return "PropertyNotify";
     default:
       if (ev->type == damage_event + XDamageNotify) {
         return "Damage";
@@ -1999,8 +2066,13 @@
 static Window
 ev_window(XEvent *ev) {
   switch (ev->type) {
-    case Expose:
-      return ev->xexpose.window;
+    case FocusIn:
+    case FocusOut:
+      return ev->xfocus.window;
+    case CreateNotify:
+      return ev->xcreatewindow.window;
+    case ConfigureNotify:
+      return ev->xconfigure.window;
     case MapNotify:
       return ev->xmap.window;
     case UnmapNotify:
@@ -2009,6 +2081,10 @@
       return ev->xreparent.window;
     case CirculateNotify:
       return ev->xcirculate.window;
+    case Expose:
+      return ev->xexpose.window;
+    case PropertyNotify:
+      return ev->xproperty.window;
     default:
       if (ev->type == damage_event + XDamageNotify) {
         return ((XDamageNotifyEvent *)ev)->drawable;
@@ -2058,6 +2134,9 @@

 inline static void
 ev_configure_notify(XConfigureEvent *ev) {
+#if DEBUG_EVENTS
+  printf("{ send_event: %d, above: %08lx, override_redirect: %d }\n", ev->send_event, ev->above, ev->override_redirect);
+#endif
   configure_win(dpy, ev);
 }

@@ -2160,14 +2239,33 @@

 inline static void
 ev_handle(XEvent *ev) {
+
+#if DEBUG_EVENTS
+  Window w;
+  char *window_name;
+  Bool to_free = False;
+#endif
+
   if ((ev->type & 0x7f) != KeymapNotify) {
     discard_ignore(dpy, ev->xany.serial);
   }

 #if DEBUG_EVENTS
+  w = ev_window(ev);
+  window_name = "(Failed to get title)";
+  if (w) {
+    if (root == w)
+      window_name = "(Root window)";
+    else
+      to_free = window_get_name(w, &window_name);
+  }
   if (ev->type != damage_event + XDamageNotify) {
-    printf("event %10.10s serial 0x%08x window 0x%08x\n",
-      ev_name(ev), ev_serial(ev), ev_window(ev));
+    printf("event %10.10s serial %#010x window %#010lx \"%s\"\n",
+      ev_name(ev), ev_serial(ev), w, window_name);
+  }
+  if (to_free) {
+    XFree(window_name);
+    window_name = NULL;
   }
 #endif

This patch traces calls to restack_win() and prints the revised window stack. I applied a similar patch to xcompmgr, and this is its output: (I replaced some window IDs with their actual function):

(Also, in order to obtain some cleaner output, I disabled window borders, handles, and titlebars in fvwm.)

event PropertyNo serial 0x0000015d window 0x00000291
event CreateNoti serial 0x0000020d window 0x00c001ed
event   Event 33 serial 0x00000214 window 0x00000000
event ConfigureN serial 0x00000215 window 0x00c001ed
event CreateNoti serial 0x00000247 window <Outer frame of "Save As">
event   Reparent serial 0x00000246 window 0x00c001ed
event ConfigureN serial 0x00000251 window <Outer frame of "Save As">
restack_win(<Outer frame of "Save As">, <Outer frame of tmux>): Window stack modified. Current stack:
0xe00001 "(null)" -> 0x8000f4 "(null)" -> 0x8000c9 "(null)" -> 0x8000c1 "(null)" -> 0xc00001 "Vim" -> 0x400003 "(null)" -> 0x400002 "(null)" -> 0x8000c6 "(null)" -> 0x8000c5 "(null)" -> 0x8000c4 "(null)" -> 0x8000c3 "(null)" -> 0x8000c2 "(null)" -> 0x80007c "FVWM" -> <Outer frame of "Save As"> "(null)" -> <Outer frame of tmux> "(null)" -> <Outer frame of gVim> "(null)" -> 0x8000c7 "(null)" ->
event ConfigureN serial 0x00000268 window <Outer frame of gVim>
restack_win(<Outer frame of gVim>, <Outer frame of tmux>): Window stack modified. Current stack:
0xe00001 "(null)" -> 0x8000f4 "(null)" -> 0x8000c9 "(null)" -> 0x8000c1 "(null)" -> 0xc00001 "Vim" -> 0x400003 "(null)" -> 0x400002 "(null)" -> 0x8000c6 "(null)" -> 0x8000c5 "(null)" -> 0x8000c4 "(null)" -> 0x8000c3 "(null)" -> 0x8000c2 "(null)" -> 0x80007c "FVWM" -> <Outer frame of "Save As"> "(null)" -> <Outer frame of gVim> "(null)" -> <Outer frame of tmux> "(null)" -> 0x8000c7 "(null)" ->
event PropertyNo serial 0x00000280 window 0x00000291
event        Map serial 0x0000026a window <Outer frame of "Save As">
event PropertyNo serial 0x00000286 window 0x00000291
event PropertyNo serial 0x00000286 window 0x00000291
event PropertyNo serial 0x00000286 window 0x00000291
event PropertyNo serial 0x000002c9 window 0x00000291

Two calls to restack_win(). Now look at compton's output in the same situation:

event   FocusOut serial 0x00000146 window <Outer frame of tmux> "(null)"
event    FocusIn serial 0x00000146 window <Outer frame of gVim> "(null)"
event PropertyNo serial 0x00000147 window 0x000291 "(Root window)"
event PropertyNo serial 0x00000229 window 0xc00003 "[No Name] - GVIM"
event CreateNoti serial 0x0000024a window 0xc00dc7 "Save As"
event   Event 33 serial 0x00000252 window 00000000 "(Failed to get title)"
event ConfigureN serial 0x00000252 window 0xc00dc7 "Save As"
{ send_event: 0, above: 01000001, override_redirect: 0 }
event CreateNoti serial 0x00000253 window <Outer frame of "Save As"> "(null)"
event   Reparent serial 0x00000253 window 0xc00dc7 "Save As"
event ConfigureN serial 0x0000025c window <Outer frame of "Save As"> "(null)"
{ send_event: 0, above: 008000de, override_redirect: 0 }
restack_win(<Outer frame of "Save As">, <Outer frame of tmux>): Window stack modified. Current stack:
0x1000001 "(null)" -> 0x8000f4 "(null)" -> 0xe00001 "(null)" -> 0x8000c9 "(null)" -> 0x8000c1 "(null)" -> 0xc00001 "Vim" -> 0x400003 "(null)" -> 0x400002 "(null)" -> 0x8000c6 "(null)" -> 0x8000c5 "(null)" -> 0x8000c4 "(null)" -> 0x8000c3 "(null)" -> 0x8000c2 "(null)" -> 0x80007c "FVWM" -> <Outer frame of "Save As"> "(null)" -> <Outer frame of tmux> "(null)" -> <Outer frame of gVim> "(null)" -> 0x8000c7 "(null)" ->
event ConfigureN serial 0x0000025c window <Outer frame of gVim> "(null)"
{ send_event: 0, above: 008000de, override_redirect: 0 }
restack_win(<Outer frame of gVim>, <Outer frame of tmux>): Window stack modified. Current stack:
0x1000001 "(null)" -> 0x8000f4 "(null)" -> 0xe00001 "(null)" -> 0x8000c9 "(null)" -> 0x8000c1 "(null)" -> 0xc00001 "Vim" -> 0x400003 "(null)" -> 0x400002 "(null)" -> 0x8000c6 "(null)" -> 0x8000c5 "(null)" -> 0x8000c4 "(null)" -> 0x8000c3 "(null)" -> 0x8000c2 "(null)" -> 0x80007c "FVWM" -> <Outer frame of "Save As"> "(null)" -> <Outer frame of gVim> "(null)" -> <Outer frame of tmux> "(null)" -> 0x8000c7 "(null)" ->
event PropertyNo serial 0x0000025c window 0x000291 "(Root window)"
event        Map serial 0x0000026f window <Outer frame of "Save As"> "(null)"
restack_win(<Outer frame of "Save As">, <Outer frame of tmux>): Window stack modified. Current stack:
0x1000001 "(null)" -> 0x8000f4 "(null)" -> 0xe00001 "(null)" -> 0x8000c9 "(null)" -> 0x8000c1 "(null)" -> 0xc00001 "Vim" -> 0x400003 "(null)" -> 0x400002 "(null)" -> 0x8000c6 "(null)" -> 0x8000c5 "(null)" -> 0x8000c4 "(null)" -> 0x8000c3 "(null)" -> 0x8000c2 "(null)" -> 0x80007c "FVWM" -> <Outer frame of gVim> "(null)" -> <Outer frame of "Save As"> "(null)" -> <Outer frame of tmux> "(null)" -> 0x8000c7 "(null)" ->
event   FocusOut serial 0x0000026f window <Outer frame of gVim> "(null)"
event PropertyNo serial 0x00000270 window 0x000291 "(Root window)"
event PropertyNo serial 0x00000270 window 0x000291 "(Root window)"
event PropertyNo serial 0x00000270 window 0x000291 "(Root window)"
event PropertyNo serial 0x00000287 window 0x000291 "(Root window)"

3 calls to restack_win(), last one causes the very issue.

chjj commented 12 years ago

Awesome. Great work. Unfortunately, I haven't had time to work on compton lately. It's a great feeling to get some help. :)

I'll review this and merge it soon. This is one of 3 major bugs that needed fixing.

hanschen commented 12 years ago

@richardgv: Your patch seems to work well here (xmonad 0.10 on Arch). Fantastic! This was probably the most annoying bug on my system, and you just fixed it - thanks a lot.