1 // -*- mode: C; indent-tabs-mode: nil; -*-
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 PyObject
*OtkDisplay_New(char *name
)
40 XModifierKeymap
*modmap
;
41 unsigned int NumLockMask
= 0, ScrollLockMask
= 0;
47 self
= PyObject_New(OtkDisplay
, &OtkDisplay_Type
);
50 if (!(self
->display
= XOpenDisplay(name
))) {
51 printf(_("Unable to open connection to the X server. Please set the \n\
52 DISPLAY environment variable approriately, or use the '-display' command \n\
53 line argument.\n\n"));
56 if (fcntl(ConnectionNumber(self
->display
), F_SETFD
, 1) == -1) {
57 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
61 XSetErrorHandler(xerrorHandler
);
63 // set the DISPLAY environment variable for any lauched children, to the
64 // display we're using, so they open in the right place.
65 disp_env
= PyString_FromFormat("DISPLAY=%s", DisplayString(self
->display
));
66 if (putenv(PyString_AsString(disp_env
))) {
67 printf(_("warning: couldn't set environment variable 'DISPLAY'\n"));
72 // find the availability of X extensions we like to use
74 self
->shape
= XShapeQueryExtension(self
->display
,
75 &self
->shape_event_basep
, &junk
);
79 self
->xinerama
= XineramaQueryExtension(self
->display
,
80 &self
->xinerama_event_basep
, &junk
);
83 // get lock masks that are defined by the display (not constant)
84 modmap
= XGetModifierMapping(self
->display
);
85 if (modmap
&& modmap
->max_keypermod
> 0) {
86 const int mask_table
[] = {
87 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
88 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
90 const size_t size
= (sizeof(mask_table
) / sizeof(mask_table
[0])) *
91 modmap
->max_keypermod
;
92 // get the values of the keyboard lock modifiers
93 // Note: Caps lock is not retrieved the same way as Scroll and Num lock
94 // since it doesn't need to be.
95 const KeyCode num_lock
= XKeysymToKeycode(self
->display
, XK_Num_Lock
);
96 const KeyCode scroll_lock
= XKeysymToKeycode(self
->display
,
99 for (cnt
= 0; cnt
< size
; ++cnt
) {
100 if (! modmap
->modifiermap
[cnt
]) continue;
102 if (num_lock
== modmap
->modifiermap
[cnt
])
103 NumLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
104 if (scroll_lock
== modmap
->modifiermap
[cnt
])
105 ScrollLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
109 if (modmap
) XFreeModifiermap(modmap
);
111 self
->mask_list
[0] = 0;
112 self
->mask_list
[1] = LockMask
;
113 self
->mask_list
[2] = NumLockMask
;
114 self
->mask_list
[3] = LockMask
| NumLockMask
;
115 self
->mask_list
[4] = ScrollLockMask
;
116 self
->mask_list
[5] = ScrollLockMask
| LockMask
;
117 self
->mask_list
[6] = ScrollLockMask
| NumLockMask
;
118 self
->mask_list
[7] = ScrollLockMask
| LockMask
| NumLockMask
;
120 // Get information on all the screens which are available.
121 self
->screenInfoList
= PyList_New(ScreenCount(self
->display
));
122 for (i
= 0; i
< ScreenCount(self
->display
); ++i
)
123 PyList_SetItem(self
->screenInfoList
, i
, OtkScreenInfo_New(i
));
125 self
->gccache
= OtkGCCache_New(PyList_Size(self
->screenInfoList
));
127 return (PyObject
*)self
;
130 void OtkDisplay_Grab(OtkDisplay
*self
)
133 if (self
->grab_count
== 0)
134 XGrabServer(self
->display
);
138 void OtkDisplay_Ungrab(OtkDisplay
*self
)
140 if (self
->grab_count
== 0) return;
142 if (self
->grab_count
== 0)
143 XUngrabServer(self
->display
);
148 static PyObject
*otkdisplay_grab(OtkDisplay
* self
, PyObject
* args
)
150 if (!PyArg_ParseTuple(args
, ":grab"))
152 OtkDisplay_Grab(self
);
156 static PyObject
*otkdisplay_ungrab(OtkDisplay
* self
, PyObject
* args
)
158 if (!PyArg_ParseTuple(args
, ":ungrab"))
160 OtkDisplay_Ungrab(self
);
164 static PyMethodDef get_methods
[] = {
165 {"grab", (PyCFunction
)otkdisplay_grab
, METH_VARARGS
,
166 "Grab the X display."},
167 {"ungrab", (PyCFunction
)otkdisplay_ungrab
, METH_VARARGS
,
168 "Ungrab/Release the X display."},
169 {NULL
, NULL
, 0, NULL
}
174 static void otkdisplay_dealloc(PyObject
* self
)
176 XCloseDisplay(((OtkDisplay
*) self
)->display
);
177 PyObject_Del(((OtkDisplay
*) self
)->screenInfoList
);
181 static PyObject
*otkdisplay_getattr(PyObject
*obj
, char *name
)
183 return Py_FindMethod(get_methods
, obj
, name
);
187 PyTypeObject OtkDisplay_Type
= {
188 PyObject_HEAD_INIT(NULL
)
193 otkdisplay_dealloc
, /*tp_dealloc*/
195 otkdisplay_getattr
, /*tp_getattr*/
200 0, /*tp_as_sequence*/
206 static int xerrorHandler(Display
*d
, XErrorEvent
*e
)
211 //if (e->error_code != BadWindow)
213 XGetErrorText(d
, e
->error_code
, errtxt
, 128);
214 printf("X Error: %s\n", errtxt
);