1 // -*- mode: C; indent-tabs-mode: nil; -*-
5 #include <X11/keysym.h>
8 #include <X11/extensions/shape.h>
13 #endif // HAVE_STDIO_H
17 #endif // HAVE_STDLIB_H
21 #endif // HAVE_FCNTL_H
24 # include <sys/types.h>
26 #endif // HAVE_UNISTD_H
28 #include "../src/gettext.h"
30 extern PyTypeObject OtkDisplay_Type
;
32 static int xerrorHandler(Display
*d
, XErrorEvent
*e
);
34 PyObject
*OtkDisplay_New(char *name
)
38 XModifierKeymap
*modmap
;
39 unsigned int NumLockMask
= 0, ScrollLockMask
= 0;
45 self
= PyObject_New(OtkDisplay
, &OtkDisplay_Type
);
48 if (!(self
->display
= XOpenDisplay(name
))) {
49 printf(_("Unable to open connection to the X server. Please set the \n\
50 DISPLAY environment variable approriately, or use the '-display' command \n\
51 line argument.\n\n"));
54 if (fcntl(ConnectionNumber(self
->display
), F_SETFD
, 1) == -1) {
55 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
59 XSetErrorHandler(xerrorHandler
);
61 // set the DISPLAY environment variable for any lauched children, to the
62 // display we're using, so they open in the right place.
63 disp_env
= PyString_FromFormat("DISPLAY=%s", DisplayString(self
->display
));
64 if (putenv(PyString_AsString(disp_env
))) {
65 printf(_("warning: couldn't set environment variable 'DISPLAY'\n"));
70 // find the availability of X extensions we like to use
72 self
->shape
= XShapeQueryExtension(self
->display
,
73 &self
->shape_event_basep
, &junk
);
77 self
->xinerama
= XineramaQueryExtension(self
->display
,
78 &self
->xinerama_event_basep
, &junk
);
81 // get lock masks that are defined by the display (not constant)
82 modmap
= XGetModifierMapping(self
->display
);
83 if (modmap
&& modmap
->max_keypermod
> 0) {
84 const int mask_table
[] = {
85 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
86 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
88 const size_t size
= (sizeof(mask_table
) / sizeof(mask_table
[0])) *
89 modmap
->max_keypermod
;
90 // get the values of the keyboard lock modifiers
91 // Note: Caps lock is not retrieved the same way as Scroll and Num lock
92 // since it doesn't need to be.
93 const KeyCode num_lock
= XKeysymToKeycode(self
->display
, XK_Num_Lock
);
94 const KeyCode scroll_lock
= XKeysymToKeycode(self
->display
,
97 for (cnt
= 0; cnt
< size
; ++cnt
) {
98 if (! modmap
->modifiermap
[cnt
]) continue;
100 if (num_lock
== modmap
->modifiermap
[cnt
])
101 NumLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
102 if (scroll_lock
== modmap
->modifiermap
[cnt
])
103 ScrollLockMask
= mask_table
[cnt
/ modmap
->max_keypermod
];
107 if (modmap
) XFreeModifiermap(modmap
);
109 self
->mask_list
[0] = 0;
110 self
->mask_list
[1] = LockMask
;
111 self
->mask_list
[2] = NumLockMask
;
112 self
->mask_list
[3] = LockMask
| NumLockMask
;
113 self
->mask_list
[4] = ScrollLockMask
;
114 self
->mask_list
[5] = ScrollLockMask
| LockMask
;
115 self
->mask_list
[6] = ScrollLockMask
| NumLockMask
;
116 self
->mask_list
[7] = ScrollLockMask
| LockMask
| NumLockMask
;
118 // Get information on all the screens which are available.
119 self
->screenInfoList
= PyList_New(ScreenCount(self
->display
));
120 for (i
= 0; i
< ScreenCount(self
->display
); ++i
)
121 PyList_Append(self
->screenInfoList
, OtkScreenInfo_New(i
));
123 self
->gccache
= OtkGCCache_New(PyList_Size(self
->screenInfoList
));
125 return (PyObject
*)self
;
128 void OtkDisplay_Grab(OtkDisplay
*self
)
131 if (self
->grab_count
== 0)
132 XGrabServer(self
->display
);
136 void OtkDisplay_Ungrab(OtkDisplay
*self
)
138 if (self
->grab_count
== 0) return;
140 if (self
->grab_count
== 0)
141 XUngrabServer(self
->display
);
146 static PyObject
*otkdisplay_grab(OtkDisplay
* self
, PyObject
* args
)
148 if (!PyArg_ParseTuple(args
, ":grab"))
150 OtkDisplay_Grab(self
);
154 static PyObject
*otkdisplay_ungrab(OtkDisplay
* self
, PyObject
* args
)
156 if (!PyArg_ParseTuple(args
, ":ungrab"))
158 OtkDisplay_Ungrab(self
);
162 static PyMethodDef get_methods
[] = {
163 {"grab", (PyCFunction
)otkdisplay_grab
, METH_VARARGS
,
164 "Grab the X display."},
165 {"ungrab", (PyCFunction
)otkdisplay_ungrab
, METH_VARARGS
,
166 "Ungrab/Release the X display."},
167 {NULL
, NULL
, 0, NULL
}
172 static void otkdisplay_dealloc(PyObject
* self
)
174 XCloseDisplay(((OtkDisplay
*) self
)->display
);
175 PyObject_Del(((OtkDisplay
*) self
)->screenInfoList
);
179 static PyObject
*otkdisplay_getattr(PyObject
*obj
, char *name
)
181 return Py_FindMethod(get_methods
, obj
, name
);
185 PyTypeObject OtkDisplay_Type
= {
186 PyObject_HEAD_INIT(NULL
)
191 otkdisplay_dealloc
, /*tp_dealloc*/
193 otkdisplay_getattr
, /*tp_getattr*/
198 0, /*tp_as_sequence*/
204 static int xerrorHandler(Display
*d
, XErrorEvent
*e
)
209 //if (e->error_code != BadWindow)
211 XGetErrorText(d
, e
->error_code
, errtxt
, 128);
212 printf("X Error: %s\n", errtxt
);