Mercurial > projects > dynamin
annotate dynamin/gui/x_window.d @ 106:acdbb30fee7e
Port to D2.
Most of the effort was dealing with immutable and const.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Mon, 17 Dec 2012 23:41:50 -0600 |
parents | 73060bc3f004 |
children |
rev | line source |
---|---|
0 | 1 |
2 /* | |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
74
diff
changeset
|
3 * Copyright Jordan Miner |
0 | 4 * |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
74
diff
changeset
|
5 * This Source Code Form is subject to the terms of the Mozilla Public |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
74
diff
changeset
|
6 * License, v. 2.0. If a copy of the MPL was not distributed with this |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
74
diff
changeset
|
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
0 | 8 * |
9 */ | |
10 | |
11 module dynamin.gui.x_window; | |
12 | |
13 public import dynamin.core.string; | |
14 public import dynamin.core.global; | |
15 public import dynamin.core.math; | |
16 public import dynamin.gui.window; | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
17 public import dynamin.gui.key; |
0 | 18 public import dynamin.c.xlib; |
19 public import dynamin.c.xlib : XWindow = Window; | |
20 public import dynamin.c.xmu; | |
21 public import dynamin.c.cairo; | |
22 public import dynamin.c.cairo_xlib; | |
23 public import tango.stdc.string; | |
24 public import tango.io.Stdout; | |
25 | |
26 /* | |
27 ** Window property: | |
28 ** _NET_FRAME_EXTENTS(CARDINAL) = 4, 4, 23, 4 | |
29 ** left, right, top and bottom border sizes | |
30 */ | |
31 | |
32 Window[XWindow] windows; | |
33 void setControl(XWindow handle, Window win) { | |
34 if(win is null) | |
35 windows.remove(handle); | |
36 else | |
37 windows[handle] = win; | |
38 } | |
39 | |
40 Window getControl(XWindow handle) { | |
41 auto tmp = handle in windows; | |
42 return tmp is null ? null : *tmp; | |
43 } | |
44 | |
45 /** | |
46 * A simpler method that returns all the data in a property. | |
47 * NOTE: the returned data still has to be freed with XFree() | |
48 */ | |
49 void* getXWindowProperty(XDisplay* d, XWindow w, XAtom prop, int* numRet = null) { | |
50 XAtom actualType; | |
51 int actualFormat; | |
52 uint nitems, bytesAfter; | |
53 void* ptr; | |
54 XGetWindowProperty(d, w, prop, | |
55 0, 0xFFFFFFFF, false, AnyPropertyType, | |
56 &actualType, &actualFormat, &nitems, &bytesAfter, | |
57 &ptr); | |
58 if(numRet) *numRet = nitems; | |
59 return ptr; | |
60 } | |
61 bool isWMPropertySupported(XAtom prop) { | |
62 int count; | |
63 XAtom* atoms = cast(XAtom*)getXWindowProperty(display, | |
64 root, XA._NET_SUPPORTED, &count); | |
65 scope(exit) XFree(atoms); | |
66 for(int i = 0; i < count; ++i) | |
67 if(atoms[i] == prop) | |
68 return true; | |
69 return false; | |
70 } | |
71 bool isTopLevelReparented(XWindow w) { | |
72 XWindow root, parent; | |
73 XWindow* children; | |
74 uint numChildren; | |
75 XQueryTree(display, w, | |
76 &root, &parent, &children, &numChildren); | |
77 return parent != root; | |
78 } | |
79 | |
80 XDisplay* display; | |
81 XWindow root; | |
82 XWindow msgWin; | |
83 abstract class XA { // X atoms | |
84 static: | |
85 XAtom _NET_SUPPORTED, _NET_WM_NAME, _NET_WORKAREA, _NET_FRAME_EXTENTS; | |
86 XAtom _NET_REQUEST_FRAME_EXTENTS; | |
87 XAtom _NET_MOVERESIZE_WINDOW; | |
88 XAtom _NET_WM_WINDOW_TYPE; | |
89 XAtom _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_UTILITY; | |
90 XAtom _NET_WM_WINDOW_TYPE_SPLASH; | |
91 XAtom _NET_WM_WINDOW_TYPE_DIALOG, _NET_WM_WINDOW_TYPE_NORMAL; | |
92 XAtom WM_PROTOCOLS, WM_DELETE_WINDOW, _NET_WM_SYNC_REQUEST; | |
93 XAtom UTF8_STRING, ATOM; | |
94 XAtom _MOTIF_WM_HINTS; | |
95 XAtom CLIPBOARD, PRIMARY, TARGETS, CLIPBOARD_MANAGER, SAVE_TARGETS; | |
96 XAtom DYNAMIN_SELECTION; | |
97 } | |
98 static this() { | |
99 display = XOpenDisplay(null); | |
100 if(!display) | |
101 Stdout("XOpenDisplay() failed").newline; | |
102 root = XRootWindow(display, XDefaultScreen(display)); | |
103 | |
104 msgWin = XCreateSimpleWindow(display, root, 0, 0, 1, 1, 0, 0, 0); | |
105 | |
106 XA._NET_SUPPORTED = XInternAtom(display, "_NET_SUPPORTED", false); | |
107 XA._NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", false); | |
108 XA._NET_WORKAREA = XInternAtom(display, "_NET_WORKAREA", false); | |
109 XA._NET_FRAME_EXTENTS = XInternAtom(display, "_NET_FRAME_EXTENTS", false); | |
110 XA._NET_REQUEST_FRAME_EXTENTS = | |
111 XInternAtom(display, "_NET_REQUEST_FRAME_EXTENTS", false); | |
112 XA._NET_MOVERESIZE_WINDOW = | |
113 XInternAtom(display, "_NET_MOVERESIZE_WINDOW", false); | |
114 XA._NET_WM_WINDOW_TYPE = | |
115 XInternAtom(display, "_NET_WM_WINDOW_TYPE", false); | |
116 XA._NET_WM_WINDOW_TYPE_MENU = | |
117 XInternAtom(display, "_NET_WM_WINDOW_TYPE_MENU", false); | |
118 XA._NET_WM_WINDOW_TYPE_UTILITY = | |
119 XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", false); | |
120 XA._NET_WM_WINDOW_TYPE_SPLASH = | |
121 XInternAtom(display, "_NET_WM_WINDOW_TYPE_SPLASH", false); | |
122 XA._NET_WM_WINDOW_TYPE_DIALOG = | |
123 XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", false); | |
124 XA._NET_WM_WINDOW_TYPE_NORMAL = | |
125 XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", false); | |
126 XA.WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", false); | |
127 XA.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", false); | |
128 XA._NET_WM_SYNC_REQUEST = | |
129 XInternAtom(display, "_NET_WM_SYNC_REQUEST", false); | |
130 XA.UTF8_STRING = XInternAtom(display, "UTF8_STRING", false); | |
131 XA.ATOM = XInternAtom(display, "ATOM", false); | |
132 XA._MOTIF_WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", false); | |
133 XA.CLIPBOARD = XInternAtom(display, "CLIPBOARD", false); | |
134 XA.PRIMARY = XInternAtom(display, "PRIMARY", false); | |
135 XA.TARGETS = XInternAtom(display, "TARGETS", false); | |
136 XA.CLIPBOARD_MANAGER = XInternAtom(display, "CLIPBOARD_MANAGER", false); | |
137 XA.SAVE_TARGETS = XInternAtom(display, "SAVE_TARGETS", false); | |
138 | |
139 XA.DYNAMIN_SELECTION = XInternAtom(display, "DYNAMIN_SELECTION", false); | |
140 if(!isWMPropertySupported(XA._NET_WM_NAME)) | |
141 Stdout("warning: WM does not support _NET_WM_NAME").newline; | |
142 if(!isWMPropertySupported(XA._NET_WORKAREA)) | |
143 Stdout("warning: WM does not support _NET_WORKAREA").newline; | |
144 if(!isWMPropertySupported(XA._NET_FRAME_EXTENTS)) | |
145 Stdout("warning: WM does not support _NET_FRAME_EXTENTS").newline; | |
146 if(!isWMPropertySupported(XA._NET_WORKAREA)) | |
147 Stdout("warning: WM does not support _NET_WORKAREA").newline; | |
148 } | |
149 | |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
150 struct InvalidRect { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
151 Window window; |
0 | 152 int x, y, width, height; |
153 } | |
154 | |
155 static class PaintQueue { | |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
156 import tango.util.container.LinkedList; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
157 import dynamin.painting.graphics; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
158 import dynamin.gui.events; |
0 | 159 static: |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
160 LinkedList!(InvalidRect) rects; |
0 | 161 static this() { |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
162 rects = new LinkedList!(InvalidRect)(); |
0 | 163 } |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
164 void add(Window win, int x, int y, int width, int height) { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
165 auto iter = rects.iterator; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
166 InvalidRect* r; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
167 while((r = iter.next()) !is null) { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
168 if(r.window == win && shouldMerge(r.x, r.y, r.width, r.height, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
169 x, y, width, height)) { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
170 join(r.x, r.y, r.width, r.height, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
171 x, y, width, height); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
172 return; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
173 } |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
174 } |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
175 InvalidRect rect; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
176 rect.window = win; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
177 rect.x = x; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
178 rect.y = y; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
179 rect.width = width; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
180 rect.height = height; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
181 rects.add(rect); |
0 | 182 } |
183 bool shouldMerge(int x1, int y1, int width1, int height1, | |
184 int x2, int y2, int width2, int height2) { | |
185 return x2 <= x1 + width1 && y2 <= y1 + height1 && | |
186 x2 + width2 >= x1 && y2 + height2 >= y1; | |
187 } | |
106 | 188 void join(ref int x, ref int y, ref int width, ref int height, |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
189 int x2, int y2, int width2, int height2) { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
190 auto minx = min(x, x2); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
191 auto miny = min(y, y2); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
192 width = max(x+width, x2+width2)-minx; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
193 height = max(y+height, y2+height2)-miny; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
194 x = minx; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
195 y = miny; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
196 } |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
197 void paint() { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
198 if(rects.size == 0) |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
199 return; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
200 auto iter = rects.iterator; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
201 InvalidRect* r; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
202 while((r = iter.next()) !is null) |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
203 paint(r); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
204 rects.clear(); |
0 | 205 } |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
206 void paint(InvalidRect* rect) { |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
207 auto surfaceWin = cairo_xlib_surface_create( |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
208 display, rect.window.handle, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
209 XDefaultVisual(display, XDefaultScreen(display)), |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
210 cast(int)rect.window.width, cast(int)rect.window.height); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
211 // TODO: ^ should be contentWidth/height or got from evWindow |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
212 auto crWin = cairo_create(surfaceWin); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
213 cairo_surface_destroy(surfaceWin); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
214 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
215 auto surfaceBuff = cairo_surface_create_similar(surfaceWin, CAIRO_CONTENT_COLOR, rect.width, rect.height); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
216 auto crBuff = cairo_create(surfaceBuff); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
217 cairo_translate(crBuff, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
218 -rect.x-rect.window.borderSize.left, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
219 -rect.y-rect.window.borderSize.top); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
220 cairo_surface_destroy(surfaceBuff); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
221 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
222 cairo_set_source_rgb(crBuff, rect.window.content.backColor.R/255.0, rect.window.content.backColor.G/255.0, rect.window.content.backColor.B/255.0); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
223 cairo_paint(crBuff); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
224 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
225 cairo_set_source_rgb(crBuff, 0, 0, 0); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
226 cairo_set_line_width(crBuff, 1.0); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
227 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
228 auto g = new Graphics(crBuff); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
229 scope args = new PaintingEventArgs(g); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
230 rect.window.painting(args); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
231 delete g; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
232 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
233 cairo_set_source_surface(crWin, surfaceBuff, rect.x, rect.y); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
234 cairo_rectangle(crWin, rect.x, rect.y, rect.width, rect.height); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
235 cairo_fill(crWin); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
236 |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
237 cairo_destroy(crBuff); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
238 cairo_destroy(crWin); |
0 | 239 } |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
240 } |
0 | 241 |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
242 Key prevKey = Key.None; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
243 |
0 | 244 //{{{ ApplicationBackend |
245 template ApplicationBackend() { | |
246 void backend_run(Window w) { | |
247 bool isWindowVisible() { | |
248 if(w is null) return true; | |
249 return w.visible; | |
250 } | |
251 XEvent ev; | |
252 while(isWindowVisible()) { | |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
253 if(XEventsQueued(display, QueuedAlready) == 0) |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
254 PaintQueue.paint(); |
0 | 255 XNextEvent(display, &ev); |
256 auto evDisplay = ev.xany.display; | |
257 auto evWindow = ev.xany.window; | |
258 Window c = getControl(evWindow); | |
259 // c will be null for SelectionRequest events | |
260 //if(c is null) | |
261 // continue; | |
262 //{{{ helper functions | |
263 void createMouseEvent(void delegate(MouseEventArgs args) func) { | |
264 MouseButton button; | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
265 auto buttonEv = &ev.xbutton; |
0 | 266 switch(buttonEv.button) { |
267 case 1: button = MouseButton.Left; break; | |
268 case 2: button = MouseButton.Middle; break; | |
269 case 3: button = MouseButton.Right; break; | |
270 default: return; | |
271 } | |
272 scope args = new MouseEventArgs(buttonEv.x+c._borderSize.left, buttonEv.y+c._borderSize.top, button); | |
273 func(args); | |
274 } | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
275 bool isKeyDown(uint keycode) { |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
276 ubyte[32] keys; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
277 XQueryKeymap(display, keys.ptr); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
278 return cast(bool)( (keys[keycode / 8] >> (keycode % 8)) & 1 ); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
279 } |
0 | 280 //}}} |
281 switch(ev.type) { | |
282 case MapNotify: | |
283 c.mapped = true; | |
284 break; | |
285 case UnmapNotify: | |
286 c.mapped = false; | |
287 break; | |
288 case DestroyNotify: | |
289 setControl(evWindow, null); | |
290 break; | |
291 case ClientMessage: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
292 auto clientEv = &ev.xclient; |
0 | 293 if(clientEv.message_type != XA.WM_PROTOCOLS) |
294 break; | |
295 if(clientEv.data.l[0] == XA.WM_DELETE_WINDOW) { | |
296 XDestroyWindow(evDisplay, evWindow); | |
297 return; // TODO: check event, and figure out what to do | |
298 } | |
299 break; | |
300 case KeyPress: | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
301 auto sym = XLookupKeysym(&ev.xkey, 0); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
302 if(sym == NoSymbol) |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
303 break; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
304 // Since X gives no way to tell if a KeyPress is generated by |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
305 // auto-repeat, prevKey is used here to tell. |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
306 auto k = KeysymToKey(sym); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
307 scope args = new KeyEventArgs(k, k == prevKey); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
308 prevKey = k; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
309 Control focused = c.focusedControl ? c.focusedControl : c; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
310 focused.keyDown(args); |
0 | 311 break; |
312 case KeyRelease: | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
313 // When X does auto-repeat for a held down key, it sends |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
314 // a KeyPress and KeyRelease every time, even though the key is |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
315 // down constantly. Here we check if the key is down, and if so, |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
316 // not send a keyUp event. |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
317 if(isKeyDown(ev.xkey.keycode)) |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
318 break; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
319 auto sym = XLookupKeysym(&ev.xkey, 0); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
320 if(sym == NoSymbol) |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
321 break; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
322 auto k = KeysymToKey(sym); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
323 if(k == prevKey) |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
324 prevKey = Key.None; // can't repeat after released |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
325 scope args = new KeyEventArgs(k, false); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
326 Control focused = c.focusedControl ? c.focusedControl : c; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
327 focused.keyUp(args); |
0 | 328 break; |
329 case ButtonPress: | |
32
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
330 // 4 = scroll up, 5 = scroll down |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
331 // 6 = scroll left, 7 = scroll right |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
332 auto b = ev.xbutton.button; |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
333 if(b == 4 || b == 5) { |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
334 scope args = new MouseTurnedEventArgs(b == 4 ? -3:3, false); |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
335 c.getDescendantAtPoint( |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
336 ev.xbutton.x+c._borderSize.left, |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
337 ev.xbutton.y+c._borderSize.top).mouseTurned(args); |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
338 break; |
b48d3f2f570d
Implement mouseTurned event with X.
Jordan Miner <jminer7@gmail.com>
parents:
25
diff
changeset
|
339 } |
0 | 340 createMouseEvent((MouseEventArgs args) { c.mouseDown(args); }); |
341 break; | |
342 case ButtonRelease: | |
343 createMouseEvent((MouseEventArgs args) { c.mouseUp(args); }); | |
344 break; | |
345 case MotionNotify: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
346 auto motionEv = &ev.xmotion; |
0 | 347 Control captor = getCaptorControl(); |
348 Point pt = Point(motionEv.x+c.borderSize.left, motionEv.y+c.borderSize.top); | |
349 if(captor) | |
350 pt = c.contentToContent(pt, captor); | |
351 else | |
352 captor = c; | |
353 scope args = new MouseEventArgs(pt.x, pt.y, MouseButton.None); | |
354 if(motionEv.state & | |
355 (Button1Mask | Button2Mask | Button3Mask)) { | |
356 captor.mouseDragged(args); | |
357 } else | |
358 captor.mouseMoved(args); | |
359 break; | |
360 case EnterNotify: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
361 auto enterEv = &ev.xcrossing; |
25
0577e8738dc8
Handle EnterNotify and LeaveNotify in the X backend,
Jordan Miner <jminer7@gmail.com>
parents:
24
diff
changeset
|
362 scope args = new MouseEventArgs(enterEv.x+c.borderSize.left, |
0577e8738dc8
Handle EnterNotify and LeaveNotify in the X backend,
Jordan Miner <jminer7@gmail.com>
parents:
24
diff
changeset
|
363 enterEv.y+c.borderSize.top, MouseButton.None); |
0577e8738dc8
Handle EnterNotify and LeaveNotify in the X backend,
Jordan Miner <jminer7@gmail.com>
parents:
24
diff
changeset
|
364 c.mouseMoved(args); |
0 | 365 break; |
366 case LeaveNotify: | |
25
0577e8738dc8
Handle EnterNotify and LeaveNotify in the X backend,
Jordan Miner <jminer7@gmail.com>
parents:
24
diff
changeset
|
367 setHotControl(null); |
0 | 368 break; |
369 case FocusIn: | |
370 break; | |
371 case FocusOut: | |
372 break; | |
373 case Expose: | |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
374 auto exposeEv = &ev.xexpose; |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
375 PaintQueue.add(c, exposeEv.x, exposeEv.y, exposeEv.width, exposeEv.height); |
0 | 376 break; |
377 case PropertyNotify: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
378 auto propertyEv = &ev.xproperty; |
0 | 379 if(propertyEv.atom == XA._NET_FRAME_EXTENTS && |
380 propertyEv.state != PropertyDelete) | |
381 c.backend_nativeToBorderSize(); | |
382 break; | |
383 case ConfigureNotify: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
384 auto configureEv = &ev.xconfigure; |
0 | 385 c.repaint(); |
386 c.backend_nativeToLocationSize(); | |
387 break; | |
388 case SelectionRequest: | |
34
e4d290aaa7ed
Use pointers to X event structs to avoid copying them.
Jordan Miner <jminer7@gmail.com>
parents:
33
diff
changeset
|
389 auto selReqEv = &ev.xselectionrequest; |
0 | 390 XEvent fullEv; |
391 auto selEv = &fullEv.xselection; | |
392 selEv.type = SelectionNotify; | |
393 selEv.requestor = selReqEv.requestor; | |
394 selEv.selection = selReqEv.selection; | |
395 selEv.target = selReqEv.target; | |
396 if(selReqEv.property != None) | |
397 selEv.property = selReqEv.property; | |
398 else | |
399 selEv.property = XA.DYNAMIN_SELECTION; | |
400 selEv.time = selReqEv.time; | |
401 Stdout.format("requestor: {}", selReqEv.requestor).newline; | |
402 Stdout.format("target: {}", selReqEv.target).newline; | |
403 ClipboardData* data; // change to array when supporting multiple | |
404 if(selReqEv.selection == XA.CLIPBOARD) | |
405 data = &Clipboard.data; | |
406 else if(selReqEv.selection == XA.PRIMARY) | |
407 data = &Selection.data; | |
408 else { | |
409 selEv.property = None; | |
410 XSendEvent(display, selEv.requestor, false, 0, &fullEv); | |
411 break; | |
412 } | |
413 if(selReqEv.target == XA.TARGETS) { | |
414 XChangeProperty(display, selEv.requestor, selEv.property, | |
415 selEv.target, 32, PropModeReplace, &data.target, 1); | |
416 XSendEvent(display, selEv.requestor, false, 0, &fullEv); | |
417 break; | |
418 } else if(selReqEv.target != data.target) { | |
419 selEv.property = None; | |
420 XSendEvent(display, selEv.requestor, false, 0, &fullEv); | |
421 break; | |
422 } | |
423 XChangeProperty(display, selEv.requestor, selEv.property, | |
424 data.target, 8, PropModeReplace, data.data, data.length); | |
425 XSendEvent(display, selEv.requestor, false, 0, &fullEv); | |
426 break; | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
427 case MappingNotify: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
428 XRefreshKeyboardMapping(&ev.xmapping); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
429 break; |
0 | 430 default: |
431 break; | |
432 } | |
433 } | |
434 } | |
18
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
435 void backend_invoke(void delegate() dg) { |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
436 // TODO: |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
437 } |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
438 void backend_invokeNow(void delegate() dg) { |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
439 // TODO: |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
440 } |
836a064828e8
Implement FileDialog/DirectoryDialog with GTK
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
441 |
0 | 442 } |
443 //}}} | |
444 | |
24
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
445 //{{{ KeysymToKey() |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
446 Key KeysymToKey(int sym) { |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
447 switch(sym) { |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
448 case XK_parenright: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
449 case XK_0: return Key.D0; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
450 case XK_exclam: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
451 case XK_1: return Key.D1; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
452 case XK_at: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
453 case XK_2: return Key.D2; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
454 case XK_numbersign: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
455 case XK_3: return Key.D3; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
456 case XK_dollar: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
457 case XK_4: return Key.D4; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
458 case XK_percent: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
459 case XK_5: return Key.D5; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
460 case XK_asciicircum: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
461 case XK_6: return Key.D6; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
462 case XK_ampersand: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
463 case XK_7: return Key.D7; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
464 case XK_asterisk: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
465 case XK_8: return Key.D8; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
466 case XK_parenleft: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
467 case XK_9: return Key.D9; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
468 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
469 case XK_F1: return Key.F1; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
470 case XK_F2: return Key.F2; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
471 case XK_F3: return Key.F3; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
472 case XK_F4: return Key.F4; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
473 case XK_F5: return Key.F5; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
474 case XK_F6: return Key.F6; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
475 case XK_F7: return Key.F7; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
476 case XK_F8: return Key.F8; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
477 case XK_F9: return Key.F9; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
478 case XK_F10: return Key.F10; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
479 case XK_F11: return Key.F11; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
480 case XK_F12: return Key.F12; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
481 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
482 case XK_Escape: return Key.Escape; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
483 case XK_Tab: return Key.Tab; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
484 case XK_BackSpace: return Key.Backspace; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
485 case XK_Return: return Key.Enter; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
486 case XK_KP_Enter: return Key.Enter; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
487 case XK_space: return Key.Space; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
488 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
489 case XK_KP_Left: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
490 case XK_Left: return Key.Left; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
491 case XK_KP_Right: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
492 case XK_Right: return Key.Right; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
493 case XK_KP_Up: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
494 case XK_Up: return Key.Up; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
495 case XK_KP_Down: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
496 case XK_Down: return Key.Down; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
497 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
498 case XK_KP_Insert: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
499 case XK_Insert: return Key.Insert; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
500 case XK_KP_Delete: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
501 case XK_Delete: return Key.Delete; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
502 case XK_KP_Home: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
503 case XK_Home: return Key.Home; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
504 case XK_KP_End: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
505 case XK_End: return Key.End; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
506 case XK_KP_Prior: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
507 case XK_Prior: return Key.PageUp; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
508 case XK_KP_Next: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
509 case XK_Next: return Key.PageDown; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
510 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
511 case XK_Print: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
512 case XK_Sys_Req: return Key.PrintScreen; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
513 case XK_Pause: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
514 case XK_Break: return Key.Pause; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
515 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
516 case XK_Caps_Lock: return Key.CapsLock; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
517 case XK_Num_Lock: return Key.NumLock; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
518 case XK_Scroll_Lock: return Key.ScrollLock; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
519 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
520 case XK_KP_0: return Key.NumPad0; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
521 case XK_KP_1: return Key.NumPad1; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
522 case XK_KP_2: return Key.NumPad2; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
523 case XK_KP_3: return Key.NumPad3; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
524 case XK_KP_4: return Key.NumPad4; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
525 case XK_KP_5: return Key.NumPad5; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
526 case XK_KP_6: return Key.NumPad6; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
527 case XK_KP_7: return Key.NumPad7; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
528 case XK_KP_8: return Key.NumPad8; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
529 case XK_KP_9: return Key.NumPad9; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
530 case XK_KP_Divide: return Key.NumPadDivide; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
531 case XK_KP_Multiply: return Key.NumPadMultiply; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
532 case XK_KP_Subtract: return Key.NumPadSubtract; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
533 case XK_KP_Add: return Key.NumPadAdd; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
534 case XK_KP_Decimal: return Key.NumPadDecimal; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
535 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
536 case XK_grave: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
537 case XK_asciitilde: return Key.Backquote; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
538 case XK_minus: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
539 case XK_underscore: return Key.Minus; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
540 case XK_equal: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
541 case XK_plus: return Key.Equals; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
542 case XK_bracketleft: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
543 case XK_braceleft: return Key.OpenBracket; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
544 case XK_bracketright: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
545 case XK_braceright: return Key.CloseBracket; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
546 case XK_backslash: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
547 case XK_bar: return Key.Backslash; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
548 case XK_semicolon: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
549 case XK_colon: return Key.Semicolon; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
550 case XK_apostrophe: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
551 case XK_quotedbl: return Key.Quote; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
552 case XK_comma: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
553 case XK_less: return Key.Comma; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
554 case XK_period: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
555 case XK_greater: return Key.Period; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
556 case XK_slash: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
557 case XK_question: return Key.Slash; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
558 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
559 //case XK_Menu: return Key.Menu; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
560 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
561 case XK_Shift_L: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
562 case XK_Shift_R: return Key.Shift; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
563 case XK_Control_L: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
564 case XK_Control_R: return Key.Control; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
565 case XK_Alt_L: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
566 case XK_Alt_R: return Key.Alt; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
567 |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
568 //case XK_: return Key.; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
569 default: |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
570 if(sym >= 0x41 && sym <= 0x5A) // Key.A - Key.Z |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
571 return cast(Key)sym; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
572 if(sym >= 0x61 && sym <= 0x7A) // Key.A - Key.Z |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
573 return cast(Key)(sym-32); |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
574 return cast(Key)0; |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
575 } |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
576 } |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
577 //}}} |
43a88caead16
Implement keyDown and keyUp events with X.
Jordan Miner <jminer7@gmail.com>
parents:
23
diff
changeset
|
578 |
0 | 579 public import tango.stdc.time; |
580 template WindowBackend() { | |
581 invariant { | |
582 //if(_handle == 0) | |
583 // return; | |
584 //XWindow root, parent; | |
585 //XWindow* children; | |
586 //uint numChildren; | |
587 //XQueryTree(display, _handle, | |
588 // &root, &parent, &children, &numChildren); | |
589 //XFree(children); | |
590 //int x, y; | |
591 //XWindow child; | |
592 //XTranslateCoordinates(display, _handle, root, 0, 0, &x, &y, &child); | |
593 //assert(_location.X == x-_borderSize.Left); | |
594 //assert(_location.Y == y-_borderSize.Top); | |
595 //XWindowAttributes attribs; | |
596 //XGetWindowAttributes(display, _handle, &attribs); | |
597 } | |
598 XWindow _handle; | |
599 bool mapped = false; | |
600 bool backend_handleCreated() { return _handle > 0; } | |
601 void backend_recreateHandle() { | |
602 auto primaryScreenNum = XDefaultScreen(display); | |
603 //XColor color; | |
604 //color.red = 65535*backColor.R/255; | |
605 //color.green = 65535*backColor.G/255; | |
606 //color.blue = 65535*backColor.B/255; | |
607 //if(XAllocColor(display, XDefaultColormap(display, primaryScreenNum), &color)) | |
608 // printf("XAllocColor() failed\n"); | |
609 | |
610 XSetWindowAttributes attribs; | |
611 attribs.bit_gravity = NorthWestGravity; | |
612 // TODO: should be backColor, and should change when backColor changes | |
613 // call XSetWindowBackground() for this | |
614 attribs.background_pixel = XWhitePixel(display, primaryScreenNum); | |
615 attribs.event_mask = | |
616 KeyPressMask | | |
617 KeyReleaseMask | | |
618 ButtonPressMask | | |
619 ButtonReleaseMask | | |
620 EnterWindowMask | | |
621 LeaveWindowMask | | |
622 PointerMotionMask | | |
623 ButtonMotionMask | | |
624 ExposureMask | | |
625 FocusChangeMask | | |
626 StructureNotifyMask | | |
627 PropertyChangeMask; | |
628 XWindow newHandle = XCreateWindow( | |
629 display, root, | |
630 cast(int)x, cast(int)y, | |
631 backend_insideWidth, backend_insideHeight, | |
632 0, CopyFromParent, InputOutput, null, | |
633 CWBitGravity | CWBackPixel | CWEventMask, &attribs); | |
634 | |
635 setControl(newHandle, this); | |
636 auto protocols = [XA.WM_DELETE_WINDOW]; | |
637 XSetWMProtocols(display, newHandle, protocols.ptr, protocols.length); | |
638 if(handleCreated) { | |
639 XDestroyWindow(display, _handle); | |
640 XSync(display, false); | |
641 } | |
642 _handle = newHandle; | |
643 text = _text; // move the text over to the new window | |
644 visible = _visible; | |
645 borderStyle = _borderStyle; | |
646 //backend_nativeToBorderSize(); | |
647 } | |
648 Graphics backend_quickCreateGraphics() { | |
74
7adc733aca2d
Change Window.quickCreateGraphics() to create the handle if not already created.
Jordan Miner <jminer7@gmail.com>
parents:
34
diff
changeset
|
649 auto surface = cairo_xlib_surface_create(display, handle, |
0 | 650 XDefaultVisual(display, XDefaultScreen(display)), |
651 cast(int)width, cast(int)height); | |
652 auto cr = cairo_create(surface); | |
653 cairo_surface_destroy(surface); | |
654 cairo_translate(cr, -borderSize.left, -borderSize.top); | |
655 auto g = new Graphics(cr); | |
656 cairo_destroy(cr); | |
657 return g; | |
658 } | |
659 void backend_visible(bool b) { | |
660 if(b) | |
661 // if not created, create the handle by calling handle() | |
662 XMapWindow(display, handle); | |
663 else | |
664 XUnmapWindow(display, _handle); | |
665 } | |
666 void backend_borderStyle(WindowBorderStyle border) { | |
667 backend_update_NET_WM_WINDOW_TYPE(); | |
668 backend_update_MOTIF_WM_HINTS(); | |
669 backend_nativeToBorderSize(); | |
670 } | |
23
d55b5b998412
Implement built-in mouse cursors with X.
Jordan Miner <jminer7@gmail.com>
parents:
18
diff
changeset
|
671 void backend_setCurrentCursor(Cursor cur) { |
d55b5b998412
Implement built-in mouse cursors with X.
Jordan Miner <jminer7@gmail.com>
parents:
18
diff
changeset
|
672 XDefineCursor(display, _handle, cur.handle); |
d55b5b998412
Implement built-in mouse cursors with X.
Jordan Miner <jminer7@gmail.com>
parents:
18
diff
changeset
|
673 } |
d55b5b998412
Implement built-in mouse cursors with X.
Jordan Miner <jminer7@gmail.com>
parents:
18
diff
changeset
|
674 |
0 | 675 void backend_repaint(Rect rect) { |
33
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
676 PaintQueue.add(this, |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
677 cast(int)(rect.x-borderSize.left), cast(int)(rect.y-borderSize.top), |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
678 cast(int)rect.width+1, cast(int)rect.height+1); |
329ce1001936
Refactor painting on X by using PaintQueue.
Jordan Miner <jminer7@gmail.com>
parents:
32
diff
changeset
|
679 //Stdout.format("invalidating x={}, y={}, width={}, height={}", rect.x, rect.y, rect.width, rect.height).newline; |
0 | 680 } |
681 void backend_resizable(bool b) { | |
682 backend_updateWM_NORMAL_HINTS(); | |
683 } | |
684 void backend_contentMinSizeChanged() { | |
685 backend_updateWM_NORMAL_HINTS(); | |
686 } | |
687 void backend_contentMaxSizeChanged() { | |
688 backend_updateWM_NORMAL_HINTS(); | |
689 } | |
690 void backend_location(Point pt) { | |
691 backend_updateWM_NORMAL_HINTS(); | |
692 backend_locationSizeToNative(); | |
693 } | |
694 void backend_size(Size size) { | |
695 backend_updateWM_NORMAL_HINTS(); | |
696 backend_locationSizeToNative(); | |
697 } | |
106 | 698 void backend_text(mstring str) { |
0 | 699 //auto tmp = str.ToCharPtr(); |
700 //XTextProperty strProperty; | |
701 //if(!XStringListToTextProperty(&tmp, 1, &strProperty)) | |
702 //printf("XStringListToTextProperty() failed - out of memory\n"); | |
703 //XSetWMName(display, _handle, &strProperty); | |
704 XChangeProperty(display, _handle, XA._NET_WM_NAME, XA.UTF8_STRING, 8, PropModeReplace, str.ptr, str.length); | |
705 } | |
706 //{{{ backend specific | |
707 void backend_updateWM_NORMAL_HINTS() { | |
708 XSizeHints* sizeHints = XAllocSizeHints(); | |
709 scope(exit) XFree(sizeHints); | |
710 sizeHints.flags = PMinSize | PMaxSize | PPosition | PSize; | |
711 if(resizable) { | |
712 sizeHints.min_width = cast(int)content.minWidth; | |
713 sizeHints.min_height = cast(int)content.minHeight; | |
714 sizeHints.max_width = | |
715 content.maxWidth > 0 ? cast(int)content.maxWidth : 30_000; | |
716 sizeHints.max_height = | |
717 content.maxHeight > 0 ? cast(int)content.maxHeight : 30_000; | |
718 } else { | |
719 sizeHints.min_width = sizeHints.max_width = backend_insideWidth; | |
720 sizeHints.min_height = sizeHints.max_height = backend_insideHeight; | |
721 } | |
722 sizeHints.x = cast(int)x; | |
723 sizeHints.y = cast(int)y; | |
724 sizeHints.width = backend_insideWidth; | |
725 sizeHints.height = backend_insideHeight; | |
726 XSetWMNormalHints(display, _handle, sizeHints); | |
727 } | |
728 void backend_update_MOTIF_WM_HINTS() { | |
729 int[4] mwmHints; | |
730 mwmHints[0] = 1 << 1; // flags | |
731 mwmHints[2] = borderStyle == WindowBorderStyle.None ? 0 : 1; // decor | |
732 XChangeProperty(display, _handle, | |
733 XA._MOTIF_WM_HINTS, XA._MOTIF_WM_HINTS, 32, PropModeReplace, mwmHints.ptr, mwmHints.length); | |
734 } | |
735 void backend_update_NET_WM_WINDOW_TYPE() { | |
736 XAtom[] atoms; | |
737 // with Metacity, the decor is not being repainted from normal>dialog | |
738 // because they are the same size | |
739 if(borderStyle == WindowBorderStyle.Dialog) | |
740 atoms = [XA._NET_WM_WINDOW_TYPE_DIALOG]; | |
741 else if(borderStyle == WindowBorderStyle.Tool) | |
742 atoms = [XA._NET_WM_WINDOW_TYPE_UTILITY]; | |
743 else | |
744 atoms = [XA._NET_WM_WINDOW_TYPE_NORMAL]; | |
745 XChangeProperty(display, _handle, | |
746 XA._NET_WM_WINDOW_TYPE, XA.ATOM, 32, PropModeReplace, atoms.ptr, atoms.length); | |
747 } | |
748 // returns what width the x window should be...not including borders | |
749 int backend_insideWidth() { | |
750 return cast(int)(size.width-borderSize.left-borderSize.right); | |
751 } | |
752 // returns what height the x window should be...not including borders | |
753 int backend_insideHeight() { | |
754 return cast(int)(size.height-borderSize.top-borderSize.bottom); | |
755 } | |
756 // applies the currently set location and size to the native X Window | |
757 void backend_locationSizeToNative() { | |
758 Point pt = _location; | |
759 if(!isTopLevelReparented(_handle)) { | |
760 pt.x = pt.x + _borderSize.left; | |
761 pt.y = pt.y + _borderSize.top; | |
762 } | |
763 XMoveResizeWindow(display, _handle, cast(int)pt.x, cast(int)pt.y, | |
764 backend_insideWidth, backend_insideHeight); | |
765 // XMoveWindow: | |
766 // Under Metacity, sets the location of the WM's frame. | |
767 // Under Compiz, sets the location of the window. | |
768 // XResizeWindow: | |
769 // Under Metacity and Compiz, sets the size of the window not | |
770 // including the WM's frame. | |
771 } | |
772 // sets location and size based on where the native X Window is | |
773 void backend_nativeToLocationSize() { | |
774 XWindow root, parent; | |
775 XWindow* children; | |
776 uint numChildren; | |
777 XQueryTree(display, _handle, | |
778 &root, &parent, &children, &numChildren); | |
779 XFree(children); | |
780 | |
781 int x, y; | |
782 XWindow child; | |
783 XTranslateCoordinates(display, _handle, root, 0, 0, &x, &y, &child); | |
784 _location.x = x - _borderSize.left; | |
785 _location.y = y - _borderSize.top; | |
786 scope args = new EventArgs; | |
787 moved(args); | |
788 XWindowAttributes attribs; | |
789 XGetWindowAttributes(display, _handle, &attribs); | |
790 _size.width = attribs.width+_borderSize.left+_borderSize.right; | |
791 _size.height = attribs.height+_borderSize.top+_borderSize.bottom; | |
792 resized(args); | |
793 | |
794 //content._location = Point(_borderSize.Left, _borderSize.Top); | |
795 //content._size = Size(attribs.width, attribs.height); | |
796 //Stdout.format("location updated to {}", _location).newline; | |
797 //Stdout.format("size updated to {}", _size).newline; | |
798 } | |
799 void backend_nativeToBorderSize() { | |
800 _borderSize = backend_getBorderSize(); | |
801 //Stdout("borderSize updated to ", _borderSize).newline; | |
802 backend_nativeToLocationSize(); | |
803 } | |
804 BorderSize backend_getBorderSize() { | |
805 if(!isWMPropertySupported(XA._NET_FRAME_EXTENTS) || | |
806 borderStyle == WindowBorderStyle.None) | |
807 return BorderSize(); | |
808 // create handle if necessary | |
809 auto reqHandle = handle; | |
810 bool requested = false; | |
811 | |
812 //{{{ requestExtents() | |
813 void requestExtents() { | |
814 if(isWMPropertySupported(XA._NET_REQUEST_FRAME_EXTENTS)) { | |
815 XEvent ev; | |
816 ev.xclient.type = ClientMessage; | |
817 ev.xclient.window = handle; | |
818 ev.xclient.message_type = XA._NET_REQUEST_FRAME_EXTENTS; | |
819 ev.xclient.format = 8; | |
820 XSendEvent(display, root, false, | |
821 SubstructureNotifyMask | SubstructureRedirectMask, &ev); | |
822 } else { // compiz and beryl do not yet support requesting | |
823 XSetWindowAttributes attribs; | |
824 reqHandle = XCreateWindow(display, | |
825 root, 0, 0, 1, 1, | |
826 0, CopyFromParent, InputOnly, null, 0, &attribs); | |
827 | |
828 XWMHints* hints = XAllocWMHints(); | |
829 scope(exit) XFree(hints); | |
830 hints.flags = InputHint; | |
831 hints.input = false; | |
832 XSetWMHints(display, reqHandle, hints); | |
833 | |
834 auto mainHandle = _handle; | |
835 _handle = reqHandle; | |
836 backend_updateWM_NORMAL_HINTS(); | |
837 backend_update_NET_WM_WINDOW_TYPE(); | |
838 backend_update_MOTIF_WM_HINTS(); | |
839 backend_visible = true; | |
840 backend_visible = false; | |
841 _handle = mainHandle; | |
842 } | |
843 requested = true; | |
844 } | |
845 //}}} | |
846 | |
847 if(!mapped) | |
848 requestExtents(); | |
849 int* extents; | |
850 while(true) { | |
851 XSync(display, false); | |
852 extents = cast(int*)getXWindowProperty(display, reqHandle, | |
853 XA._NET_FRAME_EXTENTS); | |
854 if(extents !is null) | |
855 break; | |
856 if(!requested) | |
857 requestExtents(); | |
858 } | |
859 scope(exit) XFree(extents); | |
860 if(reqHandle != _handle) | |
861 XDestroyWindow(display, reqHandle); | |
862 return BorderSize(extents[0], extents[2], extents[1], extents[3]); | |
863 } | |
864 //}}} | |
865 } | |
866 |