sending windows to workspaces works. focus messes up on fast switching
[mikachu/openbox.git] / otk_c / screeninfo.c
1 // -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "../config.h"
4 #include "screeninfo.h"
5 #include "display.h"
6 #include "rect.h"
7
8 #include <X11/Xutil.h>
9
10 #ifdef HAVE_STRING_H
11 # include <string.h>
12 #endif
13
14 #include "../src/gettext.h"
15
16 extern PyTypeObject OtkScreenInfo_Type;
17
18 PyObject *OtkScreenInfo_New(int num)
19 {
20   OtkScreenInfo* self;
21   char *dstr, *dstr2;
22   int i;
23
24   self = PyObject_New(OtkScreenInfo, &OtkScreenInfo_Type);
25
26   self->screen = num;
27   self->root_window = RootWindow(OBDisplay->display, self->screen);
28   self->rect = (OtkRect*)
29     OtkRect_New(0, 0, WidthOfScreen(ScreenOfDisplay(OBDisplay->display,
30                                                     self->screen)),
31                 HeightOfScreen(ScreenOfDisplay(OBDisplay->display,
32                                                self->screen)));
33   
34   /*
35     If the default depth is at least 8 we will use that,
36     otherwise we try to find the largest TrueColor visual.
37     Preference is given to 24 bit over larger depths if 24 bit is an option.
38   */
39
40   self->depth = DefaultDepth(OBDisplay->display, self->screen);
41   self->visual = DefaultVisual(OBDisplay->display, self->screen);
42   self->colormap = DefaultColormap(OBDisplay->display, self->screen);
43   
44   if (self->depth < 8) {
45     // search for a TrueColor Visual... if we can't find one...
46     // we will use the default visual for the screen
47     XVisualInfo vinfo_template, *vinfo_return;
48     int vinfo_nitems;
49     int best = -1;
50
51     vinfo_template.screen = self->screen;
52     vinfo_template.class = TrueColor;
53
54     vinfo_return = XGetVisualInfo(OBDisplay->display,
55                                   VisualScreenMask | VisualClassMask,
56                                   &vinfo_template, &vinfo_nitems);
57     if (vinfo_return) {
58       int max_depth = 1;
59       for (i = 0; i < vinfo_nitems; ++i) {
60         if (vinfo_return[i].depth > max_depth) {
61           if (max_depth == 24 && vinfo_return[i].depth > 24)
62             break;          // prefer 24 bit over 32
63           max_depth = vinfo_return[i].depth;
64           best = i;
65         }
66       }
67       if (max_depth < self->depth) best = -1;
68     }
69
70     if (best != -1) {
71       self->depth = vinfo_return[best].depth;
72       self->visual = vinfo_return[best].visual;
73       self->colormap = XCreateColormap(OBDisplay->display, self->root_window,
74                                        self->visual, AllocNone);
75     }
76
77     XFree(vinfo_return);
78   }
79
80   // get the default display string and strip the screen number
81   self->display_string = (PyStringObject*)
82     PyString_FromFormat("DISPLAY=%s",DisplayString(OBDisplay->display));
83   dstr = PyString_AsString((PyObject*)self->display_string);
84   dstr2 = strrchr(dstr, '.');
85   if (dstr2) {
86     PyObject *str;
87     
88     _PyString_Resize((PyObject**)&self->display_string, dstr2 - dstr);
89     str = PyString_FromFormat(".%d", self->screen);
90     PyString_Concat((PyObject**)&self->display_string, str);
91   }
92
93 #ifdef    XINERAMA
94   self->xinerama_active = False;
95
96   if (OtkDisplay->hasXineramaExtensions()) {
97     if (OtkDisplay->getXineramaMajorVersion() == 1) {
98       // we know the version 1(.1?) protocol
99
100       /*
101         in this version of Xinerama, we can't query on a per-screen basis, but
102         in future versions we should be able, so the 'activeness' is checked
103         on a pre-screen basis anyways.
104       */
105       if (XineramaIsActive(OBDisplay->display)) {
106         /*
107           If Xinerama is being used, there there is only going to be one screen
108           present. We still, of course, want to use the screen class, but that
109           is why no screen number is used in this function call. There should
110           never be more than one screen present with Xinerama active.
111         */
112         int num;
113         XineramaScreenInfo *info = XineramaQueryScreens(OBDisplay->display,
114                                                         &num);
115         if (num > 0 && info) {
116           self->xinerama_areas = PyList_New(num);
117           for (i = 0; i < num; ++i) {
118             PyList_SetItem(self->xinerama_areas, i,
119                            OtkRect_New(info[i].x_org, info[i].y_org,
120                                        info[i].width, info[i].height));
121           }
122           XFree(info);
123
124           // if we can't find any xinerama regions, then we act as if it is not
125           // active, even though it said it was
126           self->xinerama_active = True;
127         }
128       }
129     }
130   }
131 #endif // XINERAMA
132     
133   return (PyObject*)self;
134 }
135
136
137
138 static PyObject *otkscreeninfo_getscreen(OtkScreenInfo* self, PyObject* args)
139 {
140   if (!PyArg_ParseTuple(args, ":getScreen"))
141     return NULL;
142   return PyInt_FromLong(self->screen);
143 }
144
145 static OtkRect *otkscreeninfo_getrect(OtkScreenInfo* self, PyObject* args)
146 {
147   if (!PyArg_ParseTuple(args, ":getRect"))
148     return NULL;
149   return self->rect;
150 }
151
152
153 static PyMethodDef get_methods[] = {
154   {"getScreen", (PyCFunction)otkscreeninfo_getscreen, METH_VARARGS,
155    "Get the screen number."},
156   {"getRect", (PyCFunction)otkscreeninfo_getrect, METH_VARARGS,
157    "Get the area taken up by the screen."},
158   {NULL, NULL, 0, NULL}
159 };
160
161
162
163 static void otkscreeninfo_dealloc(OtkScreenInfo* self)
164 {
165   Py_DECREF(self->display_string);
166   Py_DECREF(self->rect);
167 #ifdef XINERAMA
168   Py_DECREF(self->xinerama_areas);
169 #endif
170   PyObject_Del((PyObject*)self);
171 }
172
173 static PyObject *otkscreeninfo_getattr(PyObject *obj, char *name)
174 {
175   return Py_FindMethod(get_methods, obj, name);
176 }
177
178
179 PyTypeObject OtkScreenInfo_Type = {
180   PyObject_HEAD_INIT(NULL)
181   0,
182   "OtkScreenInfo",
183   sizeof(OtkScreenInfo),
184   0,
185   (destructor)otkscreeninfo_dealloc, /*tp_dealloc*/
186   0,          /*tp_print*/
187   otkscreeninfo_getattr, /*tp_getattr*/
188   0,          /*tp_setattr*/
189   0,          /*tp_compare*/
190   0,          /*tp_repr*/
191   0,          /*tp_as_number*/
192   0,          /*tp_as_sequence*/
193   0,          /*tp_as_mapping*/
194   0,          /*tp_hash */
195 };