nux-1.14.0
XInputWindow.cpp
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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends