bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: maintaining key window on unhide


From: Matt Rice
Subject: Re: maintaining key window on unhide
Date: Sat, 21 Oct 2006 06:58:45 -0700 (PDT)

--- Fred Kiefer <fredkiefer@gmx.de> wrote:

> Hi Matt,
> 
> - There are already functions in NSWindow.m, e.g.
> NSWindowList(), which
> are supposed to return the windows in front to back
> order. Perhaps it
> would be possible to redirect these function tot he
> display server and
> implement the rest on top of them.

ok I implemented NSWindowCount and NSWindowList to do
this, after googling this function and looking at some
mailing list posts, theres a number of interesting
things about it..

it should return all window not just ones specific to
the application,

it returns window server specific window numbers for
which there is no public function to convert to actual
window numbers (where in some cases i believe no
conversion is neccesary).

which might be useful if we ever want to get
activateIgnoringOtherApps:NO to work without obscuring
the key window... but that is a whole other thing
involving external window numbers and requiring lots
of backend changes.


> 
> - There is also a method in GSDisplayServer
> windowlist, which could be
> defined to return the window ordered and implemented
> the way you want
> it. If not, lets remove this method.
> 

I implemented windowsordered as this, except instead
of returning NSWindow objects, it returns an array of
window numbers which i think was more in line with the
original intent..


> - You use the new GSDisplayServer method in various
> methods on
> NSApplication. I would prefer that we just use it,
> or which ever other
> solution you choose, in orderedWindows and use the
> later method
> everywhere else. Making this method the official
> interface for ordered
> windows.

I implemented orderedWindows to not accept panels and
documented that.
and made a fuction GSOrderedWindows();
which just converts the window numbers array into an
array of NSWindows.

when we get -gui's GSPrivate.h figured out this can be
turned into a hidden private function.

> - Your implementation of GSDIsplayServer
> windowsordered returned the
> windows ordered the other way round as
> orderedWindows has to return
> them. Why not resolve this at the level below and
> just pass the values on?

I swapped the order
 
> - It should also be possible to implement
> orderedDocuments on top of
> orderedWindows.

i'll leave this for now to someone else or another
time.

> 
> - Why are deactivate and unhide processed in
> stacking order?

got into why this happens yesterday, but i switched
these to reverse order and the others to use natural
order.




__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
Index: Source/x11/XGServerWindow.m
===================================================================
--- Source/x11/XGServerWindow.m (revision 23902)
+++ Source/x11/XGServerWindow.m (working copy)
@@ -2619,7 +2619,7 @@
        window->siz_hints.y);
       setNormalHints(dpy, window);
       /* Set this to ignore any take focus events for this window */
-      generic.desiredOrderedWindow = winNum;
+      window->ignore_take_focus = YES;
     }
 
   switch (op)
@@ -3035,7 +3035,41 @@
 
 - (NSArray *) windowlist
 {
-  return nil;
+  gswindow_device_t *rootWindow;
+  Window *windowOrder;
+  gswindow_device_t *tmp;
+  NSMutableArray *ret;
+  int c;
+  static Atom client_stack_atom = None;
+ 
+  if (!client_stack_atom)
+    client_stack_atom = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
+
+  rootWindow = [self _rootWindowForScreen:0];
+  
+  windowOrder = (Window *)PropGetCheckProperty(dpy, rootWindow->ident,
+                                              client_stack_atom,
+                                              XA_WINDOW, 32, -1, &c);
+  if (windowOrder == NULL || !c)
+    {
+      return [super windowlist];
+    }
+
+  ret = [NSMutableArray array];
+  
+  while (c-- > 0)
+    {
+      tmp = [[self class] _windowForXWindow:windowOrder[c]];
+      /* CLIENT_LIST_STACKING returns all windows on the server, we're only
+       * interested in the ones which are ours. */
+      if (tmp)
+        {
+         [ret addObject:[NSNumber numberWithInt:tmp->number]];
+        }
+    }
+  
+  XFree(windowOrder);
+  return ret;
 }
 
 - (int) windowdepth: (int)win
@@ -3328,7 +3362,6 @@
   NSDebugLLog(@"Focus", @"Setting focus to %d", window->number);
   generic.desiredFocusWindow = win;
   generic.focusRequestNumber = XNextRequest(dpy);
-  generic.desiredOrderedWindow = 0;
   XSetInputFocus(dpy, window->ident, RevertToParent, generic.lastTime);
   [inputServer ximFocusICWindow: window];
 }
Index: Source/x11/XGServerEvent.m
===================================================================
--- Source/x11/XGServerEvent.m  (revision 23902)
+++ Source/x11/XGServerEvent.m  (working copy)
@@ -1540,6 +1540,11 @@
         window to take focus after each one gets hidden. */
       NSDebugLLog(@"Focus", @"WM take focus while hiding");
     }
+  else if (cWin->ignore_take_focus == YES)
+    {
+      NSDebugLLog(@"Focus", @"Ignoring window focus request");
+      cWin->ignore_take_focus = NO;
+    }
   else if (cWin->number == key_num)
     {
       NSDebugLLog(@"Focus", @"Reasserting key window");
@@ -1555,12 +1560,6 @@
       NSDebugLLog(@"Focus", @"Key window is already %d", key_num);
       [GSServerForWindow(key_win) setinputfocus: key_num];
     }
-  else if (generic.desiredOrderedWindow == cWin->number)
-    {
-      /* We just want to order the window, not give it focus */
-      NSDebugLLog(@"Focus", @"Ignoring focus request");
-      generic.desiredOrderedWindow = 0;
-    }
   else
     {
       NSPoint eventLocation;
Index: Headers/x11/XGGeneric.h
===================================================================
--- Headers/x11/XGGeneric.h     (revision 23902)
+++ Headers/x11/XGGeneric.h     (working copy)
@@ -49,6 +49,7 @@
   Atom win_splash_atom;
   Atom win_override_atom;
   Atom win_topmenu_atom;
+  Atom net_client_list_stacking_atom;
 } XGWMWinTypes;
 
 /*
@@ -89,7 +90,6 @@
   long                 currentFocusWindow;
   long                 desiredFocusWindow;
   unsigned long                focusRequestNumber;
-  unsigned long         desiredOrderedWindow;
   unsigned char                lMouse;
   unsigned char                mMouse;
   unsigned char                rMouse;
Index: Headers/x11/XGServerWindow.h
===================================================================
--- Headers/x11/XGServerWindow.h        (revision 23902)
+++ Headers/x11/XGServerWindow.h        (working copy)
@@ -111,6 +111,7 @@
   XIC                   ic;
   void                  *gdriver;      /* gdriver ident. Managed by gdriver */
   int                   gdriverProtocol; /* Managed by gdriver */
+  BOOL                 ignore_take_focus;
 } gswindow_device_t;
 
 #define GET_XDRAWABLE(win)  ((win)->buffer ? (win)->buffer: (win)->ident)
Index: Headers/AppKit/NSGraphics.h
===================================================================
--- Headers/AppKit/NSGraphics.h (revision 23930)
+++ Headers/AppKit/NSGraphics.h (working copy)
@@ -215,6 +215,7 @@
 @class NSArray;
 @class NSWindow;
 
+APPKIT_EXPORT NSArray* GSOrderedWindows(void);
 APPKIT_EXPORT NSArray* GSAllWindows(void);
 APPKIT_EXPORT NSWindow* GSWindowWithNumber(int num);
 #endif
Index: Source/NSApplication.m
===================================================================
--- Source/NSApplication.m      (revision 23930)
+++ Source/NSApplication.m      (working copy)
@@ -522,12 +522,12 @@
        */
       if ([NSApp isHidden] == NO)
        {
-         int i;
-         NSArray *windows = RETAIN([NSApp windows]);
-      
-         for (i = 0; i < [windows count]; i++)
+         NSArray *windows = RETAIN(GSOrderedWindows());
+         NSWindow *aWin;
+         NSEnumerator *iter = [windows reverseObjectEnumerator];
+        
+         while ((aWin = [iter nextObject]))
            { 
-             NSWindow *aWin = [windows objectAtIndex:i];
               
              if ([aWin isVisible] == YES && [aWin isMiniaturized] == NO
                  && aWin != [NSApp keyWindow] && aWin != [NSApp mainWindow]
@@ -561,8 +561,10 @@
          
           RELEASE(windows);
        }
-       
-      [NSApp unhide: self];
+      else
+        {
+          [NSApp unhide: self];
+       }
     }
   else
     {
@@ -1167,6 +1169,12 @@
          [[_inactive objectAtIndex: i] orderFrontRegardless];
        }
       [_inactive removeAllObjects];
+
+      if (_unhide_on_activation)
+       {
+         [self unhide: nil];
+       }
+     
       if ([self keyWindow] == nil && _hidden_key != nil
        && [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound)
        {
@@ -1174,11 +1182,6 @@
          _hidden_key = nil;
        }
 
-      if (_unhide_on_activation)
-       {
-         [self unhide: nil];
-       }
-
       if ([self keyWindow] != nil)
        {
          [[self keyWindow] orderFront: self];
@@ -1216,13 +1219,14 @@
 {
   if (_app_is_active == YES)
     {
-      NSArray          *windows_list = [self windows]; 
-      unsigned         count = [windows_list count];
-      unsigned         i;
+      NSArray          *windows_list;
       NSDictionary     *info;
+      NSWindow         *win;
+      NSEnumerator     *iter;
 
       [nc postNotificationName: NSApplicationWillResignActiveNotification
                        object: self];
+      
 
       _app_is_active = NO;
 
@@ -1235,11 +1239,14 @@
       // This is not a problem if it is also key, and I'm not sure if it
       // is a problem at all. May be annoying in the case of workspace switch.
       [[self mainWindow] resignMainWindow];
-      for (i = 0; i < count; i++)
+      
+      windows_list = GSOrderedWindows();
+      iter = [windows_list reverseObjectEnumerator];
+
+      while ((win = [iter nextObject]))
        {
          NSModalSession theSession;
-         NSWindow      *win = [windows_list objectAtIndex: i];
-
+          
          if ([win isVisible] == NO)
            {
              continue;         /* Already invisible    */
@@ -2205,10 +2212,10 @@
 {
   if (_app_is_hidden == NO)
     {
-      NSArray          *windows_list = [self windows]; 
-      unsigned         count = [windows_list count];
+      NSArray          *windows_list;
       NSDictionary     *info;
-      unsigned         i;
+      NSWindow         *win;
+      NSEnumerator     *iter;
 
       [nc postNotificationName: NSApplicationWillHideNotification
                        object: self];
@@ -2218,10 +2225,12 @@
          _hidden_key = [self keyWindow];
          [_hidden_key resignKeyWindow];
        }
-      for (i = 0; i < count; i++)
+      
+      windows_list = GSOrderedWindows();
+      iter = [windows_list reverseObjectEnumerator];
+
+      while ((win = [iter nextObject]))
        {
-         NSWindow      *win = [windows_list objectAtIndex: i];
-
          if ([win isVisible] == NO)
            {
              continue;         /* Already invisible    */
@@ -2314,12 +2323,6 @@
          [[_hidden objectAtIndex: i] orderFrontRegardless];
        }
       [_hidden removeAllObjects];
-      if (_hidden_key != nil
-       && [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound)
-       {
-         [_hidden_key makeKeyAndOrderFront: self];
-         _hidden_key = nil;
-       }
       [[_app_icon_window contentView] setNeedsDisplay: YES];
 
       info = [self _notificationUserInfo];
@@ -2393,13 +2396,21 @@
  */
 - (NSWindow*) makeWindowsPerform: (SEL)aSelector inOrder: (BOOL)flag
 {
-  NSArray      *window_list = [self windows];
-  unsigned     i;
+  NSArray      *window_list;
+  unsigned     i, c;
 
-  // FIXME flag ignored
-  i = [window_list count];
-  while (i-- > 0)
+  // so i suppose when flag is YES it only runs on visible windows
+  if (flag)
     {
+      window_list = GSOrderedWindows();
+    }
+  else
+    {
+      window_list = [self windows];
+    }
+  
+  for (i = 0, c = [window_list count]; i < c; i++)
+    {
       NSWindow *window = [window_list objectAtIndex: i];
 
       if ([window performSelector: aSelector] != nil)
@@ -3251,14 +3262,24 @@
 }
 
 /**
- * OS X scripting method to return windows in front-to-back on-screen order.
- * <em>The GNUstep implementation returns all the windows in an arbitrary
- * order.</em>
+ * OS X scripting method to return windows in front-to-back on-screen order
+ * for scriptable windows.
+ * <em>The GNUstep implementation returns all the windows excluding NSPanels.
+ * some backends may return an array in an unspecified order.</em>
  */
 - (NSArray *) orderedWindows
 {
-  // FIXME
-  return [self windows];
+  NSArray *arr = GSOrderedWindows();
+  NSMutableArray *ret = [[NSArray alloc] initWithCapacity:[arr count]];
+  NSEnumerator *iter = [arr objectEnumerator];
+  id win;
+  while ((win = [iter nextObject]))
+    {
+      if (![win isKindOfClass:[NSPanel class]])
+        [ret addObject:win];
+    }
+  
+  return AUTORELEASE(ret);
 }
 
 /*
@@ -3478,17 +3499,17 @@
 - (void) _windowWillClose: (NSNotification*) notification
 {
   NSWindow             *win = [notification object];
-  NSArray              *windows_list = [self windows];
+  NSArray              *windows_list = GSOrderedWindows();
   unsigned             count = [windows_list count];
   unsigned             i;
   NSMutableArray       *list = [NSMutableArray arrayWithCapacity: count];
   BOOL                 wasKey = [win isKeyWindow];
   BOOL                 wasMain = [win isMainWindow];
+  NSEnumerator                 *iter = [windows_list objectEnumerator];
+  NSWindow             *tmp;
 
-  for (i = 0; i < count; i++)
+  while ((tmp = [iter nextObject]))
     {
-      NSWindow *tmp = [windows_list objectAtIndex: i];
-
       if ([tmp canBecomeMainWindow] == YES && [tmp isVisible] == YES)
        {
          [list addObject: tmp];
Index: Source/NSWindow.m
===================================================================
--- Source/NSWindow.m   (revision 23930)
+++ Source/NSWindow.m   (working copy)
@@ -4613,23 +4613,37 @@
 
 void NSCountWindows(int *count)
 {
-  *count = (int)NSCountMapTable(windowmaps);
+  *count = (int)[[GSCurrentServer() windowlist] count];
 }
 
 void NSWindowList(int size, int list[])
 {
-  NSMapEnumerator      me = NSEnumerateMapTable(windowmaps);
-  void                 *key;
-  id                   win;
-  int                  i = 0;
+  NSArray *windowList = [GSCurrentServer() windowlist];
+  unsigned i, c;
+  for (i = 0, c = [windowList count]; i < size && i < c; i++)
+    {
+      list[i] = [[windowList objectAtIndex:i] intValue];
+    }
+}
 
-  while (i < size && NSNextMapEnumeratorPair(&me, &key, (void*)&win))
+NSArray *GSOrderedWindows(void)
+{
+  NSArray *window_list = [GSCurrentServer() windowlist];
+  NSMutableArray *ret = [NSMutableArray array];
+  int i, c; 
+  
+  for (i = 0, c = [window_list count]; i < c; i++)
     {
-      list[i++] = (intptr_t)key;
+      int windowNumber = [[window_list objectAtIndex:i] intValue];
+      NSWindow *win = GSWindowWithNumber(windowNumber);
+      
+      [ret addObject:win];
     }
-/* FIXME - the list produced should be in window stacking order */
+
+  return ret;
 }
 
+
 NSArray* GSAllWindows(void)
 {
   if (windowmaps)
Index: Source/GSDisplayServer.m
===================================================================
--- Source/GSDisplayServer.m    (revision 23930)
+++ Source/GSDisplayServer.m    (working copy)
@@ -33,6 +33,7 @@
 #include <Foundation/NSThread.h>
 #include <Foundation/NSGeometry.h>
 
+#include "AppKit/NSApplication.h"
 #include "AppKit/NSEvent.h"
 #include "AppKit/NSImage.h"
 #include "AppKit/NSWindow.h"
@@ -664,11 +665,25 @@
   return 0;
 }
 
-/** Returns the list of windows that the server controls */
+/** Backends can override this method to return an array of window numbers 
+    ordered front to back.  The front most window being the first object
+    in the array.  
+    The default implementation returns the visible windows in an
+    unspecified order.
+ */
 - (NSArray *) windowlist
 {
-  [self subclassResponsibility: _cmd];
-  return nil;
+  NSMutableArray *list = [NSMutableArray arrayWithArray:[NSApp windows]];
+  int c = [list count];
+
+  while (c-- > 0)
+    {
+       if (![[list objectAtIndex:c] isVisible])
+         {
+          [list removeObjectAtIndex:c];
+         }
+    }
+  return [list valueForKey:@"windowNumber"];
 }
 
 /** Returns the depth of the window */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]