4 #include <msp/core/systemerror.h>
5 #include "display_private.h"
7 #include "window_private.h"
13 Bool match_event_type(Display *, XEvent *event, XPointer arg)
15 return event->type==*reinterpret_cast<int *>(arg);
23 void Window::platform_init()
25 DisplayHandle dpy = display.get_private().display;
27 priv->wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", true);
28 priv->invisible_cursor = 0;
29 priv->reparented = false;
33 XSetWindowAttributes attr;
34 attr.override_redirect = options.fullscreen;
35 attr.event_mask = ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask|EnterWindowMask|ExposureMask|FocusChangeMask;
37 // User position is set when the window is mapped
40 if(options.fullscreen && !options.fullscreen_exclusive)
42 const Monitor::Settings &ms = options.fullscreen_monitor->current_settings;
47 priv->window = XCreateWindow(dpy,
48 display.get_private().root_window,
50 options.width, options.height,
55 CWOverrideRedirect|CWEventMask, &attr);
57 XSetWMProtocols(dpy, priv->window, &priv->wm_delete_window, 1);
59 if(!options.resizable)
62 hints.flags = PMinSize|PMaxSize;
63 hints.min_width = hints.max_width = options.width;
64 hints.min_height = hints.max_height = options.height;
65 XSetWMNormalHints(dpy, priv->window, &hints);
69 void Window::platform_cleanup()
72 XDestroyWindow(display.get_private().display, priv->window);
74 if(priv->invisible_cursor)
75 XFreeCursor(display.get_private().display, priv->invisible_cursor);
78 void Window::set_title(const string &title)
80 vector<unsigned char> buf(title.begin(), title.end());
83 prop.encoding = XA_STRING;
85 prop.nitems = title.size();
86 XSetWMName(display.get_private().display, priv->window, &prop);
87 display.check_error();
90 void Window::platform_reconfigure(bool fullscreen_changed)
92 DisplayHandle dpy = display.get_private().display;
94 bool was_visible = visible;
95 if(fullscreen_changed)
101 // Wait for the window to be unmapped. This makes window managers happy.
103 int ev_type = UnmapNotify;
104 XPeekIfEvent(dpy, &ev, match_event_type, reinterpret_cast<char *>(&ev_type));
107 XSetWindowAttributes attr;
108 attr.override_redirect = options.fullscreen;
109 XChangeWindowAttributes(dpy, priv->window, CWOverrideRedirect, &attr);
113 if(options.resizable)
117 hints.flags = PMinSize|PMaxSize;
118 hints.min_width = hints.max_width = options.width;
119 hints.min_height = hints.max_height = options.height;
121 XSetWMNormalHints(dpy, priv->window, &hints);
123 if(options.fullscreen)
125 if(options.fullscreen_exclusive)
126 XMoveResizeWindow(dpy, priv->window, 0, 0, options.width, options.height);
129 const Monitor::Settings &ms = options.fullscreen_monitor->current_settings;
130 XMoveResizeWindow(dpy, priv->window, ms.x, ms.y, options.width, options.height);
133 else if(options.user_position)
134 XMoveResizeWindow(dpy, priv->window, options.x, options.y, options.width, options.height);
136 XResizeWindow(dpy, priv->window, options.width, options.height);
138 if(fullscreen_changed && was_visible)
142 void Window::show_cursor(bool s)
144 DisplayHandle dpy = display.get_private().display;
147 XUndefineCursor(dpy, priv->window);
150 if(!priv->invisible_cursor)
152 int screen = DefaultScreen(dpy);
154 Pixmap pm = XCreatePixmap(dpy, priv->window, 1, 1, 1);
155 GC gc = XCreateGC(dpy, pm, 0, 0);
156 XSetFunction(dpy, gc, GXclear);
157 XDrawPoint(dpy, pm, gc, 0, 0);
161 black.pixel = BlackPixel(dpy, screen);
162 XQueryColor(dpy, DefaultColormap(dpy, screen), &black);
164 priv->invisible_cursor = XCreatePixmapCursor(dpy, pm, pm, &black, &black, 0, 0);
166 XFreePixmap(dpy, pm);
168 XDefineCursor(dpy, priv->window, priv->invisible_cursor);
172 void Window::warp_pointer(int x, int y)
174 XWarpPointer(display.get_private().display, None, priv->window, 0, 0, 0, 0, x, y);
177 void Window::platform_set_touch_input()
181 void Window::platform_show()
183 DisplayHandle dpy = display.get_private().display;
184 XMapRaised(dpy, priv->window);
185 if(options.user_position && !options.fullscreen)
186 XMoveWindow(dpy, priv->window, options.x, options.y);
189 void Window::platform_hide()
191 XUnmapWindow(display.get_private().display, priv->window);
194 bool Window::event(const Event &evnt)
196 const XEvent &ev = evnt.xevent;
204 signal_input_event.emit(evnt);
206 case ConfigureNotify:
207 if((ev.xconfigure.width==static_cast<int>(options.width) && ev.xconfigure.height==static_cast<int>(options.height)) == resizing)
209 options.width = ev.xconfigure.width;
210 options.height = ev.xconfigure.height;
212 signal_resize.emit(options.width, options.height);
216 int x = ev.xconfigure.x;
217 int y = ev.xconfigure.y;
221 if(!ev.xconfigure.send_event)
223 /* If the window manager reparented us, the coordinates of a
224 real event are in the parent window's space. */
225 priv->rel_x = ev.xconfigure.x;
226 priv->rel_y = ev.xconfigure.y;
228 const Display::Private &dpy_priv = display.get_private();
230 XTranslateCoordinates(dpy_priv.display, priv->window, dpy_priv.root_window, 0, 0, &x, &y, &dummy);
233 // Use the coordinates of the window manager frame
238 if((x==options.x && y==options.y) == moving)
243 signal_move.emit(options.x, options.y);
249 priv->reparented = (ev.xreparent.parent!=display.get_private().root_window);
250 if(!priv->reparented)
257 if(ev.xclient.data.l[0]==static_cast<long>(priv->wm_delete_window))
261 if(options.fullscreen)
262 XSetInputFocus(display.get_private().display, priv->window, RevertToParent, CurrentTime);
265 if(options.fullscreen && options.fullscreen_exclusive)
266 XGrabPointer(display.get_private().display, priv->window, true, None, GrabModeAsync, GrabModeAsync, priv->window, None, CurrentTime);
269 signal_expose.emit(ev.xexpose.x, ev.xexpose.y, ev.xexpose.width, ev.xexpose.height, evnt);
272 signal_got_focus.emit();
275 signal_lost_focus.emit();
284 } // namespace Graphics