mirror of
https://github.com/gnustep/libs-back.git
synced 2025-05-30 17:00:52 +00:00
Add more EWMH methods and helper methods.
Simplify dragging support code. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@25389 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0dd2da6751
commit
32d116c7b2
3 changed files with 1198 additions and 783 deletions
|
@ -1,3 +1,9 @@
|
|||
2007-08-15 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/x11/XGServerWindow.m: Add more EWMH methods and helper
|
||||
methods for them.
|
||||
* Tools/xpbs.m: Simplify dragging support code.
|
||||
|
||||
2007-08-13 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/art/ftfont.m (-coveredCharacterSet): Correct code.
|
||||
|
|
|
@ -533,6 +533,138 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
return x;
|
||||
}
|
||||
|
||||
- (void)_sendRoot: (Window)root
|
||||
type: (Atom)type
|
||||
window: (Window)window
|
||||
data0: (long)data0
|
||||
data1: (long)data1
|
||||
data2: (long)data2
|
||||
data3: (long)data3
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.message_type = type;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.display = dpy;
|
||||
event.xclient.window = window;
|
||||
event.xclient.data.l[0] = data0;
|
||||
event.xclient.data.l[1] = data1;
|
||||
event.xclient.data.l[2] = data2;
|
||||
event.xclient.data.l[3] = data3;
|
||||
XSendEvent(dpy, root, False,
|
||||
(SubstructureNotifyMask|SubstructureRedirectMask), &event);
|
||||
XFlush(dpy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the window manager supports a feature.
|
||||
*/
|
||||
- (BOOL) _checkWMSupports: (Atom)feature
|
||||
{
|
||||
Window root;
|
||||
int count;
|
||||
Atom *data;
|
||||
Atom supported;
|
||||
|
||||
if ((generic.wm & XGWM_EWMH) != 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
supported = XInternAtom(dpy, "_NET_SUPPORTED", False);
|
||||
root = DefaultRootWindow(dpy);
|
||||
data = (Atom*)PropGetCheckProperty(dpy, root, supported, XA_ATOM, 32, -1, &count);
|
||||
if (data != 0)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < count && data[i] != feature)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
XFree(data);
|
||||
|
||||
if (i < count)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
Bool
|
||||
_get_next_prop_new_event(Display *display, XEvent *event, char *arg)
|
||||
{
|
||||
XID *data = (XID*)arg;
|
||||
|
||||
if (event->type == PropertyNotify &&
|
||||
event->xproperty.window == data[0] &&
|
||||
event->xproperty.atom == data[1] &&
|
||||
event->xproperty.state == PropertyNewValue)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) _tryRequestFrameExtents: (gswindow_device_t *)window
|
||||
{
|
||||
static Atom _net_request_frame_extents = None;
|
||||
XEvent xEvent;
|
||||
XID event_data[2];
|
||||
NSDate *limit;
|
||||
|
||||
if (_net_request_frame_extents == None)
|
||||
{
|
||||
_net_request_frame_extents = XInternAtom(dpy, "_NET_REQUEST_FRAME_EXTENTS",
|
||||
False);
|
||||
}
|
||||
|
||||
if (![self _checkWMSupports: _net_request_frame_extents])
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
event_data[0] = window->ident;
|
||||
event_data[1] = _net_request_frame_extents;
|
||||
|
||||
[self _sendRoot: window->root
|
||||
type: _net_request_frame_extents
|
||||
window: window->ident
|
||||
data0: 0
|
||||
data1: 0
|
||||
data2: 0
|
||||
data3: 0];
|
||||
|
||||
limit = [NSDate dateWithTimeIntervalSinceNow: 1.0];
|
||||
while ([limit timeIntervalSinceNow] > 0.0)
|
||||
{
|
||||
if (XCheckTypedWindowEvent(dpy, window->ident, DestroyNotify, &xEvent))
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else if (XCheckIfEvent(dpy, &xEvent, _get_next_prop_new_event,
|
||||
(char*)(&event_data)))
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(pool);
|
||||
|
||||
[NSThread sleepUntilDate:
|
||||
[NSDate dateWithTimeIntervalSinceNow: 0.01]];
|
||||
DESTROY(pool);
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) _checkStyle: (unsigned)style
|
||||
{
|
||||
|
@ -668,12 +800,14 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
window->numProtocols = 0;
|
||||
window->protocols[window->numProtocols++] = generic.take_focus_atom;
|
||||
window->protocols[window->numProtocols++] = generic.delete_win_atom;
|
||||
if ((generic.wm & XGWM_EWMH) != 0)
|
||||
{
|
||||
window->protocols[window->numProtocols++] = generic.net_wm_ping_atom;
|
||||
}
|
||||
if ((generic.wm & XGWM_WINDOWMAKER) != 0)
|
||||
{
|
||||
window->protocols[window->numProtocols++] = generic.miniaturize_atom;
|
||||
}
|
||||
// FIXME Add ping protocol for EWMH
|
||||
XSetWMProtocols(dpy, window->ident, window->protocols, window->numProtocols);
|
||||
|
||||
window->exposedRects = [NSMutableArray new];
|
||||
|
@ -700,6 +834,11 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
NSMapInsert(windowmaps, (void*)(uintptr_t)window->ident, window);
|
||||
NSMapInsert(windowtags, (void*)(uintptr_t)window->number, window);
|
||||
[self _setWindowOwnedByServer: window->number];
|
||||
|
||||
if (![self _tryRequestFrameExtents: window])
|
||||
{
|
||||
// Only display the window, if the window manager does not support
|
||||
// _NET_REQUEST_FRAME_EXTENTS
|
||||
[self orderwindow: NSWindowAbove : 0 : window->number];
|
||||
|
||||
XSync(dpy, False);
|
||||
|
@ -712,7 +851,7 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
/* In theory, after executing XSync() all events resulting from
|
||||
* our window creation and ordering front should be available in
|
||||
* the X event queue. However, it's possible that a window manager
|
||||
* could send soime events after the XSync() has been satisfied,
|
||||
* could send some events after the XSync() has been satisfied,
|
||||
* so if we have not received a visibility notification we can wait
|
||||
* for up to a second for more events.
|
||||
*/
|
||||
|
@ -755,21 +894,20 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If our window manager supports _NET_FRAME_EXTENTS we trust that as
|
||||
* definitive information.
|
||||
*/
|
||||
if (_net_frame_extents == None)
|
||||
{
|
||||
_net_frame_extents = XInternAtom(dpy,
|
||||
"_NET_FRAME_EXTENTS", False);
|
||||
_net_frame_extents = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False);
|
||||
}
|
||||
extents = (unsigned long *)PropGetCheckProperty(dpy,
|
||||
window->ident, _net_frame_extents, XA_CARDINAL, 32, 4, &count);
|
||||
if (extents != 0)
|
||||
{
|
||||
NSDebugLLog(@"Offset",
|
||||
@"Offsets retrieved from _NET_FRAME_EXTENTS");
|
||||
NSDebugLLog(@"Offset", @"Offsets retrieved from _NET_FRAME_EXTENTS");
|
||||
}
|
||||
if (extents == 0)
|
||||
{
|
||||
|
@ -803,8 +941,7 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
}
|
||||
else if (repp != 0)
|
||||
{
|
||||
NSDebugLLog(@"Offset",
|
||||
@"Offsets retrieved from ReparentNotify");
|
||||
NSDebugLLog(@"Offset", @"Offsets retrieved from ReparentNotify");
|
||||
window->parent = repp;
|
||||
if (repp != window->root)
|
||||
{
|
||||
|
@ -2052,7 +2189,6 @@ static void setWindowHintsForStyle (Display *dpy, Window window,
|
|||
extents = (unsigned long *)PropGetCheckProperty(dpy,
|
||||
win, _net_frame_extents, XA_CARDINAL, 32, 4, &count);
|
||||
|
||||
|
||||
if (!extents) // && (generic.wm & XGWM_KDE))
|
||||
{
|
||||
if (_kde_frame_strut == None)
|
||||
|
@ -2878,6 +3014,7 @@ static BOOL didCreatePixmaps;
|
|||
|
||||
- (void) setwindowlevel: (int)level : (int)win
|
||||
{
|
||||
static Atom net_wm_state_skip_pager = None;
|
||||
gswindow_device_t *window;
|
||||
|
||||
window = WINDOW_WITH_TAG(win);
|
||||
|
@ -2893,9 +3030,6 @@ static BOOL didCreatePixmaps;
|
|||
|
||||
// send WindowMaker WM window style hints
|
||||
// Always send GNUstepWMAttributes
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
/*
|
||||
* First change the window properties so that, if the window
|
||||
* is not mapped, we have stored the required info for when
|
||||
|
@ -2912,18 +3046,13 @@ static BOOL didCreatePixmaps;
|
|||
/*
|
||||
* Now send a message for rapid handling.
|
||||
*/
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.message_type = generic.win_decor_atom;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.display = dpy;
|
||||
event.xclient.window = window->ident;
|
||||
event.xclient.data.l[0] = GSWindowLevelAttr;
|
||||
event.xclient.data.l[1] = window->win_attrs.window_level;
|
||||
event.xclient.data.l[2] = 0;
|
||||
event.xclient.data.l[3] = 0;
|
||||
XSendEvent(dpy, DefaultRootWindow(dpy), False,
|
||||
SubstructureRedirectMask, &event);
|
||||
}
|
||||
[self _sendRoot: window->root
|
||||
type: generic.win_decor_atom
|
||||
window: window->ident
|
||||
data0: GSWindowLevelAttr
|
||||
data1: window->win_attrs.window_level
|
||||
data2: 0
|
||||
data3: 0];
|
||||
|
||||
if ((generic.wm & XGWM_EWMH) != 0)
|
||||
{
|
||||
|
@ -3005,22 +3134,42 @@ static BOOL didCreatePixmaps;
|
|||
*/
|
||||
if (skipTaskbar)
|
||||
{
|
||||
len = 1;
|
||||
data[0] = generic.netstates.net_wm_state_skip_taskbar_atom;
|
||||
XChangeProperty(dpy, window->ident,
|
||||
generic.netstates.net_wm_state_atom,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char *)&data, len);
|
||||
static Atom net_wm_state_add = None;
|
||||
|
||||
if (net_wm_state_add == None)
|
||||
net_wm_state_add = XInternAtom(dpy, "_NET_WM_STATE_ADD", False);
|
||||
if (net_wm_state_skip_pager == None)
|
||||
net_wm_state_skip_pager = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER",
|
||||
False);
|
||||
[self _sendRoot: window->root
|
||||
type: generic.netstates.net_wm_state_atom
|
||||
window: window->ident
|
||||
data0: net_wm_state_add
|
||||
data1: generic.netstates.net_wm_state_skip_taskbar_atom
|
||||
data2: net_wm_state_skip_pager
|
||||
data3: 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
XDeleteProperty(dpy, window->ident,
|
||||
generic.netstates.net_wm_state_atom);
|
||||
static Atom net_wm_state_remove = None;
|
||||
|
||||
if (net_wm_state_remove == None)
|
||||
net_wm_state_remove = XInternAtom(dpy, "_NET_WM_STATE_REMOVE", False);
|
||||
if (net_wm_state_skip_pager == None)
|
||||
net_wm_state_skip_pager = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER",
|
||||
False);
|
||||
|
||||
[self _sendRoot: window->root
|
||||
type: generic.netstates.net_wm_state_atom
|
||||
window: window->ident
|
||||
data0: net_wm_state_remove
|
||||
data1: generic.netstates.net_wm_state_skip_taskbar_atom
|
||||
data2: net_wm_state_skip_pager
|
||||
data3: 1];
|
||||
}
|
||||
}
|
||||
else if ((generic.wm & XGWM_GNOME) != 0)
|
||||
{
|
||||
XEvent event;
|
||||
long flag = WIN_LAYER_NORMAL;
|
||||
|
||||
if (level == NSDesktopWindowLevel)
|
||||
|
@ -3044,14 +3193,13 @@ static BOOL didCreatePixmaps;
|
|||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *)&flag, 1);
|
||||
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.window = window->ident;
|
||||
event.xclient.display = dpy;
|
||||
event.xclient.message_type = generic.wintypes.win_type_atom;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = flag;
|
||||
XSendEvent(dpy, window->root, False,
|
||||
SubstructureNotifyMask, &event);
|
||||
[self _sendRoot: window->root
|
||||
type: generic.wintypes.win_type_atom
|
||||
window: window->ident
|
||||
data0: flag
|
||||
data1: 0
|
||||
data2: 0
|
||||
data3: 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3415,24 +3563,19 @@ static BOOL didCreatePixmaps;
|
|||
if ((generic.wm & XGWM_WINDOWMAKER) != 0)
|
||||
{
|
||||
gswindow_device_t *window = WINDOW_WITH_TAG(win);
|
||||
XEvent event;
|
||||
|
||||
if (win == 0 || window == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.message_type = generic.titlebar_state_atom;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.display = dpy;
|
||||
event.xclient.window = window->ident;
|
||||
event.xclient.data.l[0] = st;
|
||||
event.xclient.data.l[1] = 0;
|
||||
event.xclient.data.l[2] = 0;
|
||||
event.xclient.data.l[3] = 0;
|
||||
XSendEvent(dpy, DefaultRootWindow(dpy), False,
|
||||
SubstructureRedirectMask, &event);
|
||||
[self _sendRoot: window->root
|
||||
type: generic.titlebar_state_atom
|
||||
window: window->ident
|
||||
data0: st
|
||||
data1: 0
|
||||
data2: 0
|
||||
data3: 0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3460,9 +3603,9 @@ static BOOL didCreatePixmaps;
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned long opacity;
|
||||
unsigned int opacity;
|
||||
|
||||
opacity = (unsigned int)(alpha * 0xffffffff);
|
||||
opacity = (unsigned int)(alpha * 0xffffffffU);
|
||||
XChangeProperty(window->display, window->ident, opacity_atom,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*)&opacity, 1L);
|
||||
|
@ -3472,9 +3615,43 @@ static BOOL didCreatePixmaps;
|
|||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*)&opacity, 1);
|
||||
}
|
||||
|
||||
// GDK uses an event to set opacity, but most window manager still wait
|
||||
// for property changes. What is the official stanard?
|
||||
}
|
||||
}
|
||||
|
||||
- (float) getAlpha: (int)win
|
||||
{
|
||||
gswindow_device_t *window = WINDOW_WITH_TAG(win);
|
||||
static Atom opacity_atom = None;
|
||||
int c;
|
||||
unsigned int *num;
|
||||
float alpha = 0.0;
|
||||
|
||||
if (win == 0 || window == 0)
|
||||
{
|
||||
NSDebugLLog(@"XGTrace", @"Setting alpha to unknown win %d", win);
|
||||
return alpha;
|
||||
}
|
||||
|
||||
/* Initialize the atom if needed */
|
||||
if (opacity_atom == None)
|
||||
opacity_atom = XInternAtom (window->display, "_NET_WM_WINDOW_OPACITY", False);
|
||||
|
||||
num = (unsigned int*)PropGetCheckProperty(dpy, window->ident,
|
||||
opacity_atom, XA_CARDINAL,
|
||||
32, 1, &c);
|
||||
|
||||
if (num)
|
||||
{
|
||||
if (*num)
|
||||
alpha = (float)*num / 0xffffffffU;
|
||||
XFree(num);
|
||||
}
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
- (void *) serverDevice
|
||||
{
|
||||
|
@ -4067,5 +4244,212 @@ _computeDepth(int class, int bpp)
|
|||
return [super iconSize];
|
||||
}
|
||||
|
||||
@end
|
||||
- (unsigned int) numberOfDesktops: (int)screen
|
||||
{
|
||||
static Atom number_of_desktops = None;
|
||||
int c;
|
||||
unsigned int *num;
|
||||
unsigned int number = 0;
|
||||
|
||||
if (number_of_desktops == None)
|
||||
number_of_desktops = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
|
||||
|
||||
num = (unsigned int*)PropGetCheckProperty(dpy, RootWindow(dpy, screen),
|
||||
number_of_desktops, XA_CARDINAL,
|
||||
32, 1, &c);
|
||||
|
||||
if (num)
|
||||
{
|
||||
number = *num;
|
||||
XFree(num);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
- (NSArray *) namesOfDesktops: (int)screen
|
||||
{
|
||||
static Atom utf8_string = None;
|
||||
static Atom desktop_names = None;
|
||||
int c;
|
||||
char *names;
|
||||
|
||||
if (utf8_string == None)
|
||||
{
|
||||
utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
|
||||
desktop_names = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
|
||||
}
|
||||
|
||||
names = (char *)PropGetCheckProperty(dpy, RootWindow(dpy, screen),
|
||||
desktop_names, utf8_string,
|
||||
0, 0, &c);
|
||||
if (names)
|
||||
{
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
char *p = names;
|
||||
|
||||
while (p < names + c - 1)
|
||||
{
|
||||
[array addObject: [NSString stringWithUTF8String: p]];
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
XFree(names);
|
||||
return AUTORELEASE(array);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (unsigned int) desktopNumberForScreen: (int)screen
|
||||
{
|
||||
static Atom current_desktop = None;
|
||||
int c;
|
||||
unsigned int *num;
|
||||
unsigned int number = 0;
|
||||
|
||||
if (current_desktop == None)
|
||||
current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
|
||||
|
||||
num = (unsigned int*)PropGetCheckProperty(dpy, RootWindow(dpy, screen),
|
||||
current_desktop, XA_CARDINAL,
|
||||
32, 1, &c);
|
||||
|
||||
if (num)
|
||||
{
|
||||
number = *num;
|
||||
XFree(num);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
- (void) setDesktopNumber: (unsigned int)workspace forScreen: (int)screen
|
||||
{
|
||||
static Atom current_desktop = None;
|
||||
Window root = RootWindow(dpy, screen);
|
||||
|
||||
if (current_desktop == None)
|
||||
current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
|
||||
|
||||
[self _sendRoot: root
|
||||
type: current_desktop
|
||||
window: root
|
||||
data0: workspace
|
||||
data1: generic.lastTime
|
||||
data2: 0
|
||||
data3: 0];
|
||||
}
|
||||
|
||||
- (unsigned int) desktopNumberForWindow: (int)win
|
||||
{
|
||||
gswindow_device_t *window;
|
||||
static Atom wm_desktop = None;
|
||||
int c;
|
||||
unsigned int *num;
|
||||
unsigned int number = 0;
|
||||
|
||||
window = WINDOW_WITH_TAG(win);
|
||||
if (!window)
|
||||
return 0;
|
||||
|
||||
if (wm_desktop == None)
|
||||
wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
|
||||
|
||||
num = (unsigned int*)PropGetCheckProperty(dpy, window->ident,
|
||||
wm_desktop, XA_CARDINAL,
|
||||
32, 1, &c);
|
||||
|
||||
if (num)
|
||||
{
|
||||
number = *num;
|
||||
XFree(num);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
- (void) setDesktopNumber: (unsigned int)workspace forWindow: (int)win
|
||||
{
|
||||
gswindow_device_t *window;
|
||||
static Atom wm_desktop = None;
|
||||
|
||||
window = WINDOW_WITH_TAG(win);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (wm_desktop == None)
|
||||
wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
|
||||
|
||||
[self _sendRoot: window->root
|
||||
type: wm_desktop
|
||||
window: window->ident
|
||||
data0: workspace
|
||||
data1: 1
|
||||
data2: 0
|
||||
data3: 0];
|
||||
}
|
||||
|
||||
- (void) setShadow: (BOOL)hasShadow : (int)win
|
||||
{
|
||||
gswindow_device_t *window;
|
||||
static Atom wm_window_shadow = None;
|
||||
unsigned long shadow;
|
||||
|
||||
window = WINDOW_WITH_TAG(win);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (wm_window_shadow == None)
|
||||
wm_window_shadow = XInternAtom(dpy, "_NET_WM_WINDOW_SHADOW", False);
|
||||
|
||||
if (hasShadow)
|
||||
{
|
||||
// FIXME: What size?
|
||||
shadow = (unsigned int)(0.1 * 0xffffffff);
|
||||
|
||||
XChangeProperty(window->display, window->ident, wm_window_shadow,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*)&shadow, 1L);
|
||||
if (window->parent != window->root)
|
||||
{
|
||||
XChangeProperty(window->display, window->parent, wm_window_shadow,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*)&shadow, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XDeleteProperty(window->display, window->ident, wm_window_shadow);
|
||||
if (window->parent != window->root)
|
||||
{
|
||||
XDeleteProperty(window->display, window->parent, wm_window_shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) hasShadow: (int)win
|
||||
{
|
||||
gswindow_device_t *window;
|
||||
static Atom wm_window_shadow = None;
|
||||
int c;
|
||||
unsigned int *num;
|
||||
BOOL hasShadow = NO;
|
||||
|
||||
window = WINDOW_WITH_TAG(win);
|
||||
if (!window)
|
||||
return hasShadow;
|
||||
|
||||
if (wm_window_shadow == None)
|
||||
wm_window_shadow = XInternAtom(dpy, "_NET_WM_WINDOW_SHADOW", False);
|
||||
|
||||
num = (unsigned int*)PropGetCheckProperty(dpy, window->ident,
|
||||
wm_window_shadow, XA_CARDINAL,
|
||||
32, 1, &c);
|
||||
|
||||
if (num)
|
||||
{
|
||||
if (*num)
|
||||
hasShadow = YES;
|
||||
XFree(num);
|
||||
}
|
||||
return hasShadow;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
95
Tools/xpbs.m
95
Tools/xpbs.m
|
@ -34,7 +34,7 @@
|
|||
/*
|
||||
* Non-predefined atoms that are used in the X selection mechanism
|
||||
*/
|
||||
static char* atom_names[] = {
|
||||
static char *atom_names[] = {
|
||||
"CHARACTER_POSITION",
|
||||
"CLIENT_WINDOW",
|
||||
"HOST_NAME",
|
||||
|
@ -54,7 +54,17 @@ static char* atom_names[] = {
|
|||
"UTF8_STRING",
|
||||
"MULTIPLE",
|
||||
"COMPOUND_TEXT",
|
||||
"INCR"
|
||||
"INCR",
|
||||
|
||||
// MIME types
|
||||
"text/plain",
|
||||
"text/uri-list",
|
||||
"application/postscript",
|
||||
"text/tab-separated-values",
|
||||
"text/richtext",
|
||||
"image/tiff",
|
||||
"application/octet-stream",
|
||||
"application/x-rootwindow-drop"
|
||||
};
|
||||
static Atom atoms[sizeof(atom_names)/sizeof(char*)];
|
||||
|
||||
|
@ -82,6 +92,8 @@ static Atom atoms[sizeof(atom_names)/sizeof(char*)];
|
|||
#define XG_MULTIPLE atoms[17]
|
||||
#define XG_COMPOUND_TEXT atoms[18]
|
||||
#define XG_INCR atoms[19]
|
||||
#define XG_MIME_PLAIN atoms[20]
|
||||
#define XG_MIME_URI atoms[21]
|
||||
|
||||
|
||||
|
||||
|
@ -565,6 +577,11 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
|
|||
if ([self data] == nil)
|
||||
[self requestData: XA_STRING];
|
||||
}
|
||||
else if ([type isEqual: NSFilenamesPboardType])
|
||||
{
|
||||
[self requestData: XG_FILE_NAME];
|
||||
}
|
||||
// FIXME: Support more types
|
||||
else
|
||||
{
|
||||
NSLog(@"Request for non-string info from X pasteboard: %@", type);
|
||||
|
@ -799,6 +816,26 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
|||
[self setData: d];
|
||||
}
|
||||
}
|
||||
else if (actual_type == XG_FILE_NAME)
|
||||
{
|
||||
NSArray *names;
|
||||
NSData *d;
|
||||
NSString *s;
|
||||
NSURL *url;
|
||||
|
||||
s = [[NSString alloc] initWithData: md
|
||||
encoding: NSUTF8StringEncoding];
|
||||
url = [[NSURL alloc] initWithString: s];
|
||||
RELEASE(s);
|
||||
if ([url isFileURL])
|
||||
{
|
||||
s = [url path];
|
||||
names = [NSArray arrayWithObject: s];
|
||||
d = [NSSerializer serializePropertyList: names];
|
||||
[self setData: d];
|
||||
}
|
||||
RELEASE(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *name = XGetAtomName(xDisplay, actual_type);
|
||||
|
@ -1023,6 +1060,25 @@ xErrorHandler(Display *d, XErrorEvent *e)
|
|||
else if ((xEvent->target == XG_FILE_NAME) &&
|
||||
[types containsObject: NSFilenamesPboardType])
|
||||
{
|
||||
NSArray *names = [_pb propertyListForType: NSFilenamesPboardType];
|
||||
NSString *file = [[names lastObject] stringByStandardizingPath];
|
||||
NSURL *url = [[NSURL alloc] initWithScheme: NSURLFileScheme
|
||||
host: @"localhost"
|
||||
path: file];
|
||||
NSString *s = [url absoluteString];
|
||||
NSData *d;
|
||||
|
||||
xType = xEvent->target;
|
||||
format = 8;
|
||||
RELEASE(url);
|
||||
d = [s dataUsingEncoding: NSISOLatin1StringEncoding];
|
||||
if (d != nil)
|
||||
{
|
||||
numItems = [d length];
|
||||
data = malloc(numItems + 1);
|
||||
if (data)
|
||||
[d getBytes: data];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1204,12 +1260,7 @@ static DndClass dnd;
|
|||
NSArray *types;
|
||||
Atom *typelist;
|
||||
|
||||
// Some GNUstep application did grap the drag pasteboard. Report this to X.
|
||||
if (xdnd_set_selection_owner(&dnd, xAppWin, None))
|
||||
{
|
||||
NSLog(@"Failed to set X drag selection owner to the pasteboard server.");
|
||||
}
|
||||
[self setOwnedByOpenStep: YES];
|
||||
[super pasteboardChangedOwner: sender];
|
||||
|
||||
// We also have to set the supported types for our window
|
||||
types = [_pb types];
|
||||
|
@ -1237,35 +1288,9 @@ static DndClass dnd;
|
|||
{
|
||||
NSString *mime = [NSPasteboard mimeTypeForPasteboardType: type];
|
||||
Atom mType = XInternAtom(xDisplay, [mime cString], False);
|
||||
Window window;
|
||||
Time whenRequested = CurrentTime;
|
||||
NSDate *limit;
|
||||
|
||||
[self setData: nil];
|
||||
// How can we get the selection owner?
|
||||
window = XGetSelectionOwner(xDisplay, dnd.XdndSelection);
|
||||
|
||||
xdnd_convert_selection(&dnd, window, xAppWin, mType);
|
||||
XFlush(xDisplay);
|
||||
|
||||
/*
|
||||
* Run an event loop to read X events until we have aquired the
|
||||
* pasteboard data we need.
|
||||
*/
|
||||
limit = [NSDate dateWithTimeIntervalSinceNow: 20.0];
|
||||
[self setWaitingForSelection: whenRequested];
|
||||
while ([self waitingForSelection] == whenRequested)
|
||||
{
|
||||
[[NSRunLoop currentRunLoop] runMode: xWaitMode
|
||||
beforeDate: limit];
|
||||
if ([limit timeIntervalSinceNow] <= 0.0)
|
||||
break; /* Timeout */
|
||||
}
|
||||
if ([self waitingForSelection] != 0)
|
||||
{
|
||||
[self setWaitingForSelection: 0];
|
||||
NSLog(@"Timed out waiting for X selection");
|
||||
}
|
||||
[self requestData: mType];
|
||||
[pb setData: [self data] forType: type];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue