1 // -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
5 #include "screeninfo.h"
7 #include <X11/keysym.h>
10 #include <X11/extensions/shape.h>
15 #endif // HAVE_STDIO_H
19 #endif // HAVE_STDLIB_H
23 #endif // HAVE_FCNTL_H
26 # include <sys/types.h>
28 #endif // HAVE_UNISTD_H
30 #include "../src/gettext.h"
32 extern PyTypeObject OtkDisplay_Type
;
34 static int xerrorHandler(Display
*d
, XErrorEvent
*e
);
36 struct OtkDisplay
*OBDisplay
= NULL
;
38 void OtkDisplay_Initialize(char *name
)
42 XModifierKeymap
*modmap
;
43 unsigned int NumLockMask
= 0, ScrollLockMask
= 0;
49 self
= PyObject_New(OtkDisplay
, &OtkDisplay_Type
);
52 if (!(self
->display
= XOpenDisplay(name
))) {
53 printf(_("Unable to open connection to the X server. Please set the \n\
54 DISPLAY environment variable approriately, or use the '-display' command \n\
55 line argument.\n\n"));
58 if (fcntl(ConnectionNumber(self
->display
), F_SETFD
, 1) == -1) {
59 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
63 XSetErrorHandler(xerrorHandler
);
65 // set the DISPLAY environment variable for any lauched children, to the
66 // display we're using, so they open in the right place.
67 disp_env
= PyString_FromFormat("DISPLAY=%s", DisplayString(self
->display
));
68 if (putenv(PyString_AsString(disp_env
))) {
69 printf(_("warning: couldn't set environment variable 'DISPLAY'\n"));
74 // find the availability of X extensions we like to use
76 self
->shape
= XShapeQueryExtension(self
->display
,
77 &self
->shape_event_basep
, &junk
);
81 self
->xinerama
= XineramaQueryExtension(self
->display
,
82 &self
->xinerama_event_basep
, &junk
);
85 // get lock masks that are defined by the display (not constant)
86 modmap
= XGetModifierMapping(self
->display
);
87 if (modmap
&& modmap
->max_keypermod
> 0) {
88 const int mask_table
[] = {
89 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
90 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
92 const size_t size
= (sizeof(mask_table
) / sizeof(mask_table
[0])) *
93 modmap
->max_keypermod
;
94 // get the values of the keyboard lock modifiers
95 // Note: Caps lock is not retrieved the same way as Scroll and Num lock
96 // since it doesn't need to be.
97 const KeyCode num_lock
= XKeysymToKeycode(self
->display
, XK_Num_Lock
);
98 const KeyCode scroll_lock
= XKeysymToKeycode(self
->display
,
101 for (cnt
= 0; cnt
< size
; ++cnt
) {
102 if (! modmap
->modifiermap
[cnt
]) continue;
104 if (num_lock
== modmap
->modifiermap
[cnt
])
105 NumLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
106 if (scroll_lock
== modmap
->modifiermap
[cnt
])
107 ScrollLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
111 if (modmap
) XFreeModifiermap(modmap
);
113 self
->mask_list
[0] = 0;
114 self
->mask_list
[1] = LockMask
;
115 self
->mask_list
[2] = NumLockMask
;
116 self
->mask_list
[3] = LockMask
| NumLockMask
;
117 self
->mask_list
[4] = ScrollLockMask
;
118 self
->mask_list
[5] = ScrollLockMask
| LockMask
;
119 self
->mask_list
[6] = ScrollLockMask
| NumLockMask
;
120 self
->mask_list
[7] = ScrollLockMask
| LockMask
| NumLockMask
;
122 // set the global var, for the new screeninfo's
125 // Get information on all the screens which are available.
126 self
->screenInfoList
= (PyListObject
*)PyList_New(ScreenCount(self
->display
));
127 for (i
= 0; i
< ScreenCount(self
->display
); ++i
)
128 PyList_SetItem((PyObject
*)self
->screenInfoList
, i
, OtkScreenInfo_New(i
));
130 Py_INCREF(OBDisplay
); // make sure it stays around!!
133 void OtkDisplay_Grab(OtkDisplay
*self
)
136 if (self
->grab_count
== 0)
137 XGrabServer(self
->display
);
141 void OtkDisplay_Ungrab(OtkDisplay
*self
)
143 if (self
->grab_count
== 0) return;
145 if (self
->grab_count
== 0)
146 XUngrabServer(self
->display
);
149 OtkScreenInfo
*OtkDisplay_ScreenInfo(OtkDisplay
*self
, int num
)
152 return (OtkScreenInfo
*)PyList_GetItem((PyObject
*)self
->screenInfoList
, num
);
156 static PyObject
*otkdisplay_grab(OtkDisplay
* self
, PyObject
* args
)
158 if (!PyArg_ParseTuple(args
, ":grab"))
160 OtkDisplay_Grab(self
);
164 static PyObject
*otkdisplay_ungrab(OtkDisplay
* self
, PyObject
* args
)
166 if (!PyArg_ParseTuple(args
, ":ungrab"))
168 OtkDisplay_Ungrab(self
);
172 static PyMethodDef get_methods
[] = {
173 {"grab", (PyCFunction
)otkdisplay_grab
, METH_VARARGS
,
174 "Grab the X display."},
175 {"ungrab", (PyCFunction
)otkdisplay_ungrab
, METH_VARARGS
,
176 "Ungrab/Release the X display."},
177 {NULL
, NULL
, 0, NULL
}
182 static void otkdisplay_dealloc(PyObject
* self
)
184 XCloseDisplay(((OtkDisplay
*) self
)->display
);
185 Py_DECREF(((OtkDisplay
*) self
)->screenInfoList
);
189 static PyObject
*otkdisplay_getattr(PyObject
*obj
, char *name
)
191 return Py_FindMethod(get_methods
, obj
, name
);
195 PyTypeObject OtkDisplay_Type
= {
196 PyObject_HEAD_INIT(NULL
)
201 otkdisplay_dealloc
, /*tp_dealloc*/
203 otkdisplay_getattr
, /*tp_getattr*/
208 0, /*tp_as_sequence*/
214 static int xerrorHandler(Display
*d
, XErrorEvent
*e
)
219 //if (e->error_code != BadWindow)
221 XGetErrorText(d
, e
->error_code
, errtxt
, 128);
222 printf("X Error: %s\n", errtxt
);