File: myX11.cpp

package info (click to toggle)
spring 88.0%2Bdfsg1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 41,524 kB
  • sloc: cpp: 343,114; ansic: 38,414; python: 12,257; java: 12,203; awk: 5,748; sh: 1,204; xml: 997; perl: 405; objc: 192; makefile: 181; php: 134; sed: 2
file content (153 lines) | stat: -rwxr-xr-x 3,504 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef HEADLESS

#include "myX11.h"

#include <string.h>
#include <string>
#include <map>

#include <SDL.h>
#if !defined(HEADLESS)
	#include <SDL_syswm.h>
#endif


void MyX11GetFrameBorderOffset(Display* display, Window& window, int* out_left, int* out_top)
{
	// XGetWindowProperty stuff
	Atom actual_type;
	int actual_format;
	unsigned long nitems;
	unsigned long bytes_remaining;
	int* data;
	int status;

	Atom net_frame_extents = XInternAtom(display, "_NET_FRAME_EXTENTS", True);

	status = XGetWindowProperty(
		display,
		window,
		net_frame_extents,
		0,      // long_offset
		4,      // long_length - we expect 4 32-bit values for _NET_FRAME_EXTENTS
		false,  // delete
		AnyPropertyType,
		&actual_type,
		&actual_format,
		&nitems,
		&bytes_remaining,
		(unsigned char**)&data);

	*out_left = *out_top = 0;
	if (status == Success) {
		if ((nitems == 4) && (bytes_remaining == 0)) {
			*out_left = data[0];
			*out_top  = data[2];
		}
		XFree(data);
	}
}

static const int windowStates = 8;
static const std::string windowStatesStr[windowStates] = {
	"_NET_WM_STATE_STICKY",
	"_NET_WM_STATE_MAXIMIZED_VERT",
	"_NET_WM_STATE_MAXIMIZED_HORZ",
	"_NET_WM_STATE_SHADED",
	"_NET_WM_STATE_HIDDEN",
	"_NET_WM_STATE_FULLSCREEN",
	"_NET_WM_STATE_ABOVE",
	"_NET_WM_STATE_BELOW"
};

int MyX11GetWindowState(Display* display, Window& window)
{
	// XGetWindowProperty stuff
	Atom actual_type;
	int actual_format;
	unsigned long nitems;
	unsigned long bytes_remaining;
	Atom* data;
	int status;

	Atom atom = XInternAtom(display, "_NET_WM_STATE", true);

	Atom windowStatesAtoms[windowStates];
	std::map<Atom,int> windowStatesInt;
	for (int i=0; i<windowStates; i++) {
		windowStatesAtoms[i] = XInternAtom(display, windowStatesStr[i].c_str(), false);
		windowStatesInt[windowStatesAtoms[i]] = 1<<i;
	}

	status = XGetWindowProperty(
		display,
		window,
		atom,
		0,
		20,
		false,
		AnyPropertyType,
		&actual_type,
		&actual_format,
		&nitems,
		&bytes_remaining,
		(unsigned char**)&data);

	if (status == Success) {
		int windowState = 0;
		for (int i=0; i<nitems; i++) {
			Atom& a = data[i];
			std::map<Atom,int>::iterator it = windowStatesInt.find(a);
			if (it != windowStatesInt.end()) {
				windowState += it->second;
			}
		}
		XFree(data);
		return windowState;
	}
	return 0;
}


void MyX11SetWindowState(Display* display, Window& window, int windowState)
{
	if (windowState <= 0)
		return;


	Atom windowStatesAtoms[windowStates];
	for (int i=0; i<windowStates; i++) {
		windowStatesAtoms[i] = XInternAtom(display, windowStatesStr[i].c_str(), false);
	}

	Atom wm_state = XInternAtom(display, "_NET_WM_STATE", False);

	XEvent xev;
	memset(&xev, 0, sizeof(xev));
	xev.type = ClientMessage;
	xev.xclient.window = window;
	xev.xclient.message_type = wm_state;
	xev.xclient.format = 32;
	xev.xclient.data.l[2] = 0;
	xev.xclient.data.l[3] = 0;

	Window root = XDefaultRootWindow(display);

	static const int _NET_WM_STATE_REMOVE = 0;
	static const int _NET_WM_STATE_ADD = 1;
	for (int i=0; i<windowStates; i++) {
		if (1<<i & windowState) {
			xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
			xev.xclient.data.l[1] = windowStatesAtoms[i];
			XSendEvent(display, root, false, SubstructureNotifyMask, &xev);
		} else {
			xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
			xev.xclient.data.l[1] = windowStatesAtoms[i];
			XSendEvent(display, root, false, SubstructureNotifyMask, &xev);
		}
	}
}

#endif // #ifndef HEADLESS