mirror of
https://github.com/gnustep/libs-back.git
synced 2025-05-30 17:00:52 +00:00
Window focus fixes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@18096 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
aa89743347
commit
74cea89a61
4 changed files with 111 additions and 58 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2003-11-19 Adam Fedor <fedor@gnu.org>
|
||||||
|
|
||||||
|
* Source/x11/XGServer.m: Add some docs.
|
||||||
|
|
||||||
|
* Window focus fixes.
|
||||||
|
* Source/x11/XGServerEvent.m ([XGServer -processEvent:event]): Move
|
||||||
|
take focus code...
|
||||||
|
([XGServer -_handleTakeFocusAtom:forContext:]): ...to here. Check for
|
||||||
|
common problems before passing event to frontend.
|
||||||
|
([XGServer -processEvent:event])(FocusOut): Invalidate current
|
||||||
|
focus window and focus request.
|
||||||
|
|
||||||
2003-11-18 16:57 Alexander Malmberg <alexander@malmberg.org>
|
2003-11-18 16:57 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/art/ftfont.m: Remove fallback ivar. Add advancementImgd
|
* Source/art/ftfont.m: Remove fallback ivar. Add advancementImgd
|
||||||
|
|
|
@ -309,6 +309,16 @@ _parse_display_name(NSString *name, int *dn, int *sn)
|
||||||
/**
|
/**
|
||||||
<unit>
|
<unit>
|
||||||
<heading>XGServer</heading>
|
<heading>XGServer</heading>
|
||||||
|
|
||||||
|
<p> XGServer is a concrete subclass of GSDisplayServer that handles
|
||||||
|
X-Window client communications. The class is broken into four sections.
|
||||||
|
The main class handles setting up and closing down the display, as well
|
||||||
|
as providing wrapper methods to access display and screen pointers. The
|
||||||
|
WindowOps category handles window creating, display, movement, and
|
||||||
|
other functions detailed in the GSDisplayServer(WindowOps) category.
|
||||||
|
The EventOps category handles events received from X-Windows and the
|
||||||
|
window manager. It implements the methods defined in the
|
||||||
|
GSDisplayServer(EventOps) category. The last section
|
||||||
</unit>
|
</unit>
|
||||||
*/
|
*/
|
||||||
@implementation XGServer
|
@implementation XGServer
|
||||||
|
|
|
@ -28,11 +28,13 @@
|
||||||
#include <AppKit/AppKitExceptions.h>
|
#include <AppKit/AppKitExceptions.h>
|
||||||
#include <AppKit/NSApplication.h>
|
#include <AppKit/NSApplication.h>
|
||||||
#include <AppKit/NSGraphics.h>
|
#include <AppKit/NSGraphics.h>
|
||||||
|
#include <AppKit/NSMenu.h>
|
||||||
#include <AppKit/NSWindow.h>
|
#include <AppKit/NSWindow.h>
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
#include <Foundation/NSArray.h>
|
#include <Foundation/NSArray.h>
|
||||||
#include <Foundation/NSDictionary.h>
|
#include <Foundation/NSDictionary.h>
|
||||||
#include <Foundation/NSData.h>
|
#include <Foundation/NSData.h>
|
||||||
|
#include <Foundation/NSNotification.h>
|
||||||
#include <Foundation/NSValue.h>
|
#include <Foundation/NSValue.h>
|
||||||
#include <Foundation/NSString.h>
|
#include <Foundation/NSString.h>
|
||||||
#include <Foundation/NSUserDefaults.h>
|
#include <Foundation/NSUserDefaults.h>
|
||||||
|
@ -97,6 +99,8 @@ static void (*procEvent)(id, SEL, XEvent*) = 0;
|
||||||
forMode: (NSString*)mode;
|
forMode: (NSString*)mode;
|
||||||
- (int) XGErrorHandler: (Display*)display : (XErrorEvent*)err;
|
- (int) XGErrorHandler: (Display*)display : (XErrorEvent*)err;
|
||||||
- (void) processEvent: (XEvent *) event;
|
- (void) processEvent: (XEvent *) event;
|
||||||
|
- (NSEvent *)_handleTakeFocusAtom: (XEvent)xEvent
|
||||||
|
forContext: (NSGraphicsContext *)gcontext;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,7 +128,7 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code)
|
||||||
return (xEvent->xkeymap.key_vector[key_code / 8] & (1 << (key_code % 8)));
|
return (xEvent->xkeymap.key_vector[key_code / 8] & (1 << (key_code % 8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation XGServer (X11Methods)
|
@implementation XGServer (EventOps)
|
||||||
|
|
||||||
- (int) XGErrorHandler: (Display*)display : (XErrorEvent*)err
|
- (int) XGErrorHandler: (Display*)display : (XErrorEvent*)err
|
||||||
{
|
{
|
||||||
|
@ -511,62 +515,8 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code)
|
||||||
else if ((Atom)xEvent.xclient.data.l[0]
|
else if ((Atom)xEvent.xclient.data.l[0]
|
||||||
== generic.take_focus_atom)
|
== generic.take_focus_atom)
|
||||||
{
|
{
|
||||||
/*
|
e = [self _handleTakeFocusAtom: xEvent
|
||||||
* WM is asking us to take the keyboard focus
|
forContext: gcontext];
|
||||||
*/
|
|
||||||
nswin = [NSApp keyWindow];
|
|
||||||
NSDebugLLog(@"Focus", @"take focus:%d (current=%d key=%d)",
|
|
||||||
cWin->number,
|
|
||||||
generic.currentFocusWindow,
|
|
||||||
[nswin windowNumber]);
|
|
||||||
if ([NSApp isActive]
|
|
||||||
&& ((generic.currentFocusWindow
|
|
||||||
&& cWin->number == generic.currentFocusWindow)
|
|
||||||
|| (generic.desiredFocusWindow
|
|
||||||
&& cWin->number != generic.desiredFocusWindow)))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Reassert our desire to have input
|
|
||||||
* focus in our existing key window.
|
|
||||||
* Case 1 can occur when we switch workspaces
|
|
||||||
* and the WM tells us to take back focus on
|
|
||||||
* our current key window, or (Case 2) if we
|
|
||||||
* asked for a window to be key but didn't get
|
|
||||||
* it (perhaps because it wasn't on-screen
|
|
||||||
* yet?).
|
|
||||||
*/
|
|
||||||
int number;
|
|
||||||
NSDebugLLog(@"Focus", @" desired focus is %d",
|
|
||||||
generic.desiredFocusWindow);
|
|
||||||
number = generic.desiredFocusWindow;
|
|
||||||
generic.focusRequestNumber = 0;
|
|
||||||
generic.desiredFocusWindow = 0;
|
|
||||||
if (number == 0)
|
|
||||||
number = generic.currentFocusWindow;
|
|
||||||
[self setinputstate: GSTitleBarKey : number];
|
|
||||||
[self setinputfocus: number];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Here the app asked for this (if nswin==nil)
|
|
||||||
* or there was a click on the title bar or
|
|
||||||
* some other reason (window mapped, etc). We don't
|
|
||||||
* necessarily want to do this for the last reason
|
|
||||||
* but we just have to deal with that since we
|
|
||||||
* can never be sure if it's necessary.
|
|
||||||
*/
|
|
||||||
eventLocation = NSMakePoint(0,0);
|
|
||||||
e = [NSEvent otherEventWithType:NSAppKitDefined
|
|
||||||
location: eventLocation
|
|
||||||
modifierFlags: 0
|
|
||||||
timestamp: 0
|
|
||||||
windowNumber: cWin->number
|
|
||||||
context: gcontext
|
|
||||||
subtype: GSAppKitWindowFocusIn
|
|
||||||
data1: 0
|
|
||||||
data2: 0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xEvent.xclient.message_type == dnd.XdndEnter)
|
else if (xEvent.xclient.message_type == dnd.XdndEnter)
|
||||||
|
@ -960,6 +910,12 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code)
|
||||||
cWin = [XGServer _windowForXWindow: xEvent.xfocus.window];
|
cWin = [XGServer _windowForXWindow: xEvent.xfocus.window];
|
||||||
NSDebugLLog(@"Focus", @"%d lost focus on %d\n",
|
NSDebugLLog(@"Focus", @"%d lost focus on %d\n",
|
||||||
xEvent.xfocus.window, (cWin) ? cWin->number : 0);
|
xEvent.xfocus.window, (cWin) ? cWin->number : 0);
|
||||||
|
generic.currentFocusWindow = 0;
|
||||||
|
if (cWin && generic.desiredFocusWindow == cWin->number)
|
||||||
|
{
|
||||||
|
/* Request not valid anymore since we lost focus */
|
||||||
|
generic.focusRequestNumber = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1054,6 +1010,8 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code)
|
||||||
if (generic.desiredFocusWindow == cWin->number
|
if (generic.desiredFocusWindow == cWin->number
|
||||||
&& generic.focusRequestNumber == 0)
|
&& generic.focusRequestNumber == 0)
|
||||||
{
|
{
|
||||||
|
NSDebugLLog(@"Focus", @"Refocusing %d on map notify",
|
||||||
|
cWin->number);
|
||||||
[self setinputfocus: cWin->number];
|
[self setinputfocus: cWin->number];
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1291,6 +1249,79 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code)
|
||||||
e = nil;
|
e = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WM is asking us to take the keyboard focus
|
||||||
|
*/
|
||||||
|
- (NSEvent *)_handleTakeFocusAtom: (XEvent)xEvent
|
||||||
|
forContext: (NSGraphicsContext *)gcontext
|
||||||
|
{
|
||||||
|
int key_num;
|
||||||
|
NSWindow *key_win;
|
||||||
|
NSEvent *e = nil;
|
||||||
|
key_win = [NSApp keyWindow];
|
||||||
|
key_num = [key_win windowNumber];
|
||||||
|
NSDebugLLog(@"Focus", @"take focus:%d (current=%d key=%d)",
|
||||||
|
cWin->number, generic.currentFocusWindow, key_num);
|
||||||
|
|
||||||
|
/* Invalidate the previous request. It's possible the app lost focus
|
||||||
|
before this request was fufilled and we are being focused again,
|
||||||
|
or ??? */
|
||||||
|
{
|
||||||
|
generic.focusRequestNumber = 0;
|
||||||
|
generic.desiredFocusWindow = 0;
|
||||||
|
}
|
||||||
|
/* We'd like to send this event directly to the front-end to handle,
|
||||||
|
but the front-end polls events so slowly compared the speed at
|
||||||
|
which X events could potentially come that we could easily get
|
||||||
|
out of sync, particularly when there are a lot of window
|
||||||
|
events */
|
||||||
|
if ([NSApp isHidden])
|
||||||
|
{
|
||||||
|
/* This often occurs when hidding an app, since a bunch of
|
||||||
|
windows get hidden at once, and the WM is searching for a
|
||||||
|
window to take focus after each one gets hidden. */
|
||||||
|
NSDebugLLog(@"Focus", @"WM take focus while hiding");
|
||||||
|
}
|
||||||
|
else if (cWin->number == key_num)
|
||||||
|
{
|
||||||
|
NSDebugLLog(@"Focus", @"Reasserting key window");
|
||||||
|
[GSServerForWindow(key_win) setinputfocus: key_num];
|
||||||
|
}
|
||||||
|
else if (key_num
|
||||||
|
&& cWin->number == [[[NSApp mainMenu] window] windowNumber])
|
||||||
|
{
|
||||||
|
/* This might occur when the window manager just wants someone
|
||||||
|
to become key, so it tells the main menu (typically the first
|
||||||
|
menu in the list), but since we already have a window that
|
||||||
|
was key before, use that instead */
|
||||||
|
NSDebugLLog(@"Focus", @"Key window is already %d", key_num);
|
||||||
|
[GSServerForWindow(key_win) setinputfocus: key_num];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSPoint eventLocation;
|
||||||
|
/*
|
||||||
|
* Here the app asked for this (if key_win==nil) or there was a
|
||||||
|
* click on the title bar or some other reason (window mapped,
|
||||||
|
* etc). We don't necessarily want to forward the event for the
|
||||||
|
* last reason but we just have to deal with that since we can
|
||||||
|
* never be sure if it's necessary.
|
||||||
|
*/
|
||||||
|
eventLocation = NSMakePoint(0,0);
|
||||||
|
e = [NSEvent otherEventWithType:NSAppKitDefined
|
||||||
|
location: eventLocation
|
||||||
|
modifierFlags: 0
|
||||||
|
timestamp: 0
|
||||||
|
windowNumber: cWin->number
|
||||||
|
context: gcontext
|
||||||
|
subtype: GSAppKitWindowFocusIn
|
||||||
|
data1: 0
|
||||||
|
data2: 0];
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Return the key_code corresponding to the user defaults string
|
// Return the key_code corresponding to the user defaults string
|
||||||
// Return 1 (which is an invalid keycode) if the user default
|
// Return 1 (which is an invalid keycode) if the user default
|
||||||
// is not set
|
// is not set
|
||||||
|
|
|
@ -319,7 +319,7 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation XGServer (DPSWindow)
|
@implementation XGServer (WindowOps)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Where a window has been reparented by the wm, we use this method to
|
* Where a window has been reparented by the wm, we use this method to
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue