nux-1.16.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com> 00019 * 00020 */ 00021 00022 #include "XInputWindow.h" 00023 #include "GraphicsDisplayX11.h" 00024 #include "GLThread.h" 00025 00026 // Jay, what is this for? It isn't referenced anywhere. 00027 #define xdnd_version 5 00028 00029 namespace nux 00030 { 00031 std::vector<Window> XInputWindow::native_windows_; 00032 00033 XInputWindow::XInputWindow(const char* title, 00034 bool take_focus, 00035 int override_redirect) 00036 : strutsEnabled_(false) 00037 , display_(GetGraphicsDisplay()->GetX11Display()) 00038 , geometry_(0, 0, 1, 1) 00039 , shown_(false) 00040 , mapped_(false) 00041 { 00042 XSetWindowAttributes attrib; 00043 00044 attrib.override_redirect = override_redirect; 00045 attrib.event_mask = KeyPressMask | 00046 KeyReleaseMask | 00047 ButtonPressMask | 00048 ButtonReleaseMask | 00049 EnterWindowMask | 00050 LeaveWindowMask | 00051 PointerMotionMask | 00052 ButtonMotionMask | 00053 PropertyChangeMask | 00054 StructureNotifyMask | 00055 FocusChangeMask; 00056 00057 window_ = XCreateWindow(display_, XDefaultRootWindow(display_), 00058 geometry_.x, geometry_.y, 00059 geometry_.width, geometry_.height, 0, 00060 CopyFromParent, InputOutput, CopyFromParent, 00061 CWOverrideRedirect | CWEventMask, &attrib); 00062 00063 native_windows_.push_back(window_); 00064 00065 Atom data[32]; 00066 int i = 0; 00067 data[i++] = XInternAtom(display_, "_NET_WM_STATE_STICKY", 0); 00068 data[i++] = XInternAtom(display_, "_NET_WM_STATE_SKIP_TASKBAR", 0); 00069 data[i++] = XInternAtom(display_, "_NET_WM_STATE_SKIP_PAGER", 0); 00070 00071 XChangeProperty(display_, window_, 00072 XInternAtom(display_, "_NET_WM_STATE", 0), 00073 XA_ATOM, 32, PropModeReplace, 00074 (unsigned char *) data, i); 00075 00076 Atom type[1]; 00077 type[0] = XInternAtom(display_, "_NET_WM_WINDOW_TYPE_DOCK", 0); 00078 XChangeProperty(display_, window_, 00079 XInternAtom(display_, "_NET_WM_WINDOW_TYPE", 0), 00080 XA_ATOM, 32, PropModeReplace, 00081 (unsigned char *) type, 1); 00082 00083 XStoreName(display_, window_, title); 00084 EnsureInputs (); 00085 00086 if (take_focus) 00087 EnableTakeFocus (); 00088 00089 EnableDnd (); 00090 } 00091 00092 XInputWindow::~XInputWindow() 00093 { 00094 native_windows_.erase(std::find (native_windows_.begin (), native_windows_.end (), window_)); 00095 XDestroyWindow(display_, window_); 00096 } 00097 00098 /* static */ 00099 std::vector<Window> const& XInputWindow::NativeHandleList() 00100 { 00101 return native_windows_; 00102 } 00103 00104 void XInputWindow::SetStruts() 00105 { 00106 int n_info; 00107 XineramaScreenInfo *info = XineramaQueryScreens (display_, &n_info); 00108 Region screen_region; 00109 Region total_screen_region = XCreateRegion (); 00110 Region input_window_region = XCreateRegion (); 00111 Region intersection = XCreateRegion (); 00112 XineramaScreenInfo monitor; 00113 XRectangle tmp_rect; 00114 int largestWidth = 0, largestHeight = 0; 00115 int screenWidth, screenHeight; 00116 long int data[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 00117 00118 /* Find the screen that this region intersects */ 00119 tmp_rect.x = geometry_.x; 00120 tmp_rect.y = geometry_.y; 00121 tmp_rect.width = geometry_.width; 00122 tmp_rect.height = geometry_.height; 00123 00124 XUnionRectWithRegion (&tmp_rect, input_window_region, input_window_region); 00125 00126 for (int i = 0; i < n_info; i++) 00127 { 00128 tmp_rect.x = info[i].x_org; 00129 tmp_rect.y = info[i].y_org; 00130 tmp_rect.width = info[i].width; 00131 tmp_rect.height = info[i].height; 00132 00133 screen_region = XCreateRegion (); 00134 00135 XUnionRectWithRegion (&tmp_rect, screen_region, screen_region); 00136 XUnionRegion (screen_region, total_screen_region, total_screen_region); 00137 XIntersectRegion (screen_region, input_window_region, intersection); 00138 00139 if (!XEmptyRegion (intersection)) 00140 { 00141 int width = intersection->extents.x2 - intersection->extents.x1; 00142 int height = intersection->extents.y2 - intersection->extents.y1; 00143 00144 if ((width * height) > (largestWidth * largestHeight)) 00145 { 00146 largestWidth = width; 00147 largestHeight = height; 00148 00149 monitor = info[i]; 00150 } 00151 } 00152 00153 XDestroyRegion (screen_region); 00154 } 00155 00156 screenWidth = total_screen_region->extents.x2 - total_screen_region->extents.x1; 00157 screenHeight = total_screen_region->extents.y2 - total_screen_region->extents.y1; 00158 00159 XDestroyRegion (input_window_region); 00160 XDestroyRegion (intersection); 00161 XDestroyRegion (total_screen_region); 00162 00163 if (info) 00164 XFree (info); 00165 00166 if (geometry_.width > geometry_.height) 00167 { 00168 if (geometry_.y - monitor.y_org < monitor.height / 2) 00169 { 00170 /* top */ 00171 data[2] = geometry_.y + geometry_.height; 00172 data[8] = geometry_.x; 00173 data[9] = geometry_.x + geometry_.width - 1; 00174 } 00175 else 00176 { 00177 /* bottom */ 00178 data[3] = (screenHeight - 1) - geometry_.y; 00179 data[10] = geometry_.x; 00180 data[11] = geometry_.x + geometry_.width - 1; 00181 } 00182 } 00183 else 00184 { 00185 if (geometry_.x - monitor.x_org < monitor.width / 2) 00186 { 00187 /* left */ 00188 data[0] = geometry_.x + geometry_.width; 00189 data[4] = geometry_.y; 00190 data[5] = geometry_.y + geometry_.height - 1; 00191 } 00192 else 00193 { 00194 /* right */ 00195 data[1] = (screenWidth - 1) - geometry_.y; 00196 data[6] = geometry_.y; 00197 data[7] = geometry_.y + geometry_.height - 1; 00198 } 00199 } 00200 00201 XChangeProperty(display_, window_, 00202 XInternAtom(display_, "_NET_WM_STRUT_PARTIAL", 0), 00203 XA_CARDINAL, 32, PropModeReplace, 00204 (unsigned char *) data, 12); 00205 } 00206 00207 void XInputWindow::UnsetStruts() 00208 { 00209 XDeleteProperty(display_, window_, 00210 XInternAtom(display_, "_NET_WM_STRUT_PARTIAL", 0)); 00211 } 00212 00213 void XInputWindow::EnableStruts(bool enable) 00214 { 00215 if (strutsEnabled_ == enable) 00216 return; 00217 00218 strutsEnabled_ = enable; 00219 if (enable) 00220 SetStruts(); 00221 else 00222 UnsetStruts(); 00223 } 00224 00225 bool XInputWindow::StrutsEnabled() 00226 { 00227 return strutsEnabled_; 00228 } 00229 00230 void XInputWindow::EnsureInputs() 00231 { 00232 XSelectInput(display_, window_, 00233 KeyPressMask | 00234 KeyReleaseMask | 00235 ButtonPressMask | 00236 ButtonReleaseMask | 00237 EnterWindowMask | 00238 LeaveWindowMask | 00239 PointerMotionMask | 00240 ButtonMotionMask | 00241 PropertyChangeMask | 00242 StructureNotifyMask | 00243 FocusChangeMask); 00244 } 00245 00246 void XInputWindow::EnableTakeFocus() 00247 { 00248 Atom wmTakeFocus = XInternAtom (display_, "WM_TAKE_FOCUS", False); 00249 XWMHints* wmHints = NULL; 00250 00251 wmHints = (XWMHints*) calloc (1, sizeof (XWMHints)); 00252 wmHints->flags |= InputHint; 00253 wmHints->input = False; 00254 XSetWMHints(display_, window_, wmHints); 00255 free(wmHints); 00256 XSetWMProtocols(display_, window_, &wmTakeFocus, 1); 00257 } 00258 00259 void XInputWindow::EnableDnd() 00260 { 00261 int version = 5; 00262 XChangeProperty(display_, window_, 00263 XInternAtom(display_, "XdndAware", false), 00264 XA_ATOM, 32, PropModeReplace, 00265 (unsigned char *) &version, 1); 00266 } 00267 00268 void XInputWindow::DisableDnd() 00269 { 00270 XDeleteProperty(display_, window_, 00271 XInternAtom(display_, "XdndAware", false)); 00272 } 00273 00275 void XInputWindow::SetGeometry(Rect const& geo) 00276 { 00277 geometry_ = geo; 00278 00279 if (shown_) 00280 XMoveResizeWindow(display_, window_, 00281 geo.x, geo.y, geo.width, geo.height); 00282 EnsureInputs(); 00283 00284 if (strutsEnabled_) 00285 SetStruts(); 00286 } 00287 00289 void XInputWindow::SetGeometry(int x, int y, int width, int height) 00290 { 00291 SetGeometry(Rect(x, y, width, height)); 00292 } 00293 00295 Rect const& XInputWindow::GetGeometry() const 00296 { 00297 return geometry_; 00298 } 00299 00300 Window XInputWindow::GetWindow () 00301 { 00302 return window_; 00303 } 00304 00305 void XInputWindow::SetInputFocus () 00306 { 00307 XSetInputFocus(display_, window_, RevertToParent, CurrentTime); 00308 } 00309 00310 void XInputWindow::Hide () 00311 { 00312 XMoveResizeWindow(display_, window_, 00313 -100 - geometry_.width, 00314 -100 - geometry_.height, 00315 geometry_.width, 00316 geometry_.height); 00317 shown_ = false; 00318 } 00319 00320 void XInputWindow::Show () 00321 { 00322 shown_ = true; 00323 00324 if (!mapped_) 00325 { 00326 XMapRaised (display_, window_); 00327 mapped_ = true; 00328 } 00329 XMoveResizeWindow(display_, window_, 00330 geometry_.x, geometry_.y, 00331 geometry_.width, geometry_.height); 00332 } 00333 } 00334