1 |
/* |
/* -*- c-basic-offset: 8 -*- |
2 |
rdesktop: A Remote Desktop Protocol client. |
rdesktop: A Remote Desktop Protocol client. |
3 |
User interface services - X Window System |
User interface services - X Window System |
4 |
Copyright (C) Matthew Chapman 1999-2002 |
Copyright (C) Matthew Chapman 1999-2002 |
23 |
#include <time.h> |
#include <time.h> |
24 |
#include <errno.h> |
#include <errno.h> |
25 |
#include "rdesktop.h" |
#include "rdesktop.h" |
26 |
|
#include "xproto.h" |
27 |
|
|
28 |
extern int width; |
extern int width; |
29 |
extern int height; |
extern int height; |
39 |
BOOL mouse_in_wnd; |
BOOL mouse_in_wnd; |
40 |
|
|
41 |
Display *display; |
Display *display; |
42 |
|
Time last_gesturetime; |
43 |
static int x_socket; |
static int x_socket; |
44 |
static Screen *screen; |
static Screen *screen; |
45 |
static Window wnd; |
Window wnd; |
46 |
static GC gc; |
static GC gc; |
47 |
static Visual *visual; |
static Visual *visual; |
48 |
static int depth; |
static int depth; |
52 |
static XModifierKeymap *mod_map; |
static XModifierKeymap *mod_map; |
53 |
static Cursor current_cursor; |
static Cursor current_cursor; |
54 |
static Atom protocol_atom, kill_atom; |
static Atom protocol_atom, kill_atom; |
55 |
|
static long input_mask; /* Needs to be global since we access it in |
56 |
|
both ui_create_window and the PropertyNotify |
57 |
|
callback functions */ |
58 |
|
|
59 |
/* endianness */ |
/* endianness */ |
60 |
static BOOL host_be; |
static BOOL host_be; |
90 |
} |
} |
91 |
PixelColour; |
PixelColour; |
92 |
|
|
93 |
|
struct _PropNotifyCb; |
94 |
|
|
95 |
|
typedef struct _PropNotifyCb |
96 |
|
{ |
97 |
|
Window wnd; |
98 |
|
Atom atom; |
99 |
|
void (*callback) (XPropertyEvent *); |
100 |
|
struct _PropNotifyCb *next; |
101 |
|
} |
102 |
|
PropNotifyCb; |
103 |
|
|
104 |
|
|
105 |
|
static PropNotifyCb *propnotify_callbacks = NULL; |
106 |
|
|
107 |
|
|
108 |
#define FILL_RECTANGLE(x,y,cx,cy)\ |
#define FILL_RECTANGLE(x,y,cx,cy)\ |
109 |
{ \ |
{ \ |
110 |
XFillRectangle(display, wnd, gc, x, y, cx, cy); \ |
XFillRectangle(display, wnd, gc, x, y, cx, cy); \ |
433 |
translate_image(int width, int height, uint8 * data) |
translate_image(int width, int height, uint8 * data) |
434 |
{ |
{ |
435 |
int size = width * height * bpp / 8; |
int size = width * height * bpp / 8; |
436 |
uint8 *out = (uint8*)xmalloc(size); |
uint8 *out = (uint8 *) xmalloc(size); |
437 |
uint8 *end = out + size; |
uint8 *end = out + size; |
438 |
|
|
439 |
switch (server_bpp) |
switch (server_bpp) |
634 |
/* todo take this out when high colour is done */ |
/* todo take this out when high colour is done */ |
635 |
printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth); |
printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth); |
636 |
|
|
637 |
|
|
638 |
|
|
639 |
return True; |
return True; |
640 |
} |
} |
641 |
|
|
662 |
XClassHint *classhints; |
XClassHint *classhints; |
663 |
XSizeHints *sizehints; |
XSizeHints *sizehints; |
664 |
int wndwidth, wndheight; |
int wndwidth, wndheight; |
665 |
long input_mask, ic_input_mask; |
long ic_input_mask; |
666 |
XEvent xevent; |
XEvent xevent; |
667 |
|
|
668 |
wndwidth = fullscreen ? WidthOfScreen(screen) : width; |
wndwidth = fullscreen ? WidthOfScreen(screen) : width; |
776 |
} |
} |
777 |
} |
} |
778 |
|
|
779 |
|
static void |
780 |
|
xwin_process_propertynotify(XPropertyEvent * xev) |
781 |
|
{ |
782 |
|
PropNotifyCb *this = propnotify_callbacks; |
783 |
|
while (NULL != this) |
784 |
|
{ |
785 |
|
if (xev->window == this->wnd && xev->atom == this->atom) |
786 |
|
{ |
787 |
|
this->callback(xev); |
788 |
|
} |
789 |
|
this = this->next; |
790 |
|
} |
791 |
|
} |
792 |
|
|
793 |
|
|
794 |
/* Process all events in Xlib queue |
/* Process all events in Xlib queue |
795 |
Returns 0 after user quit, 1 otherwise */ |
Returns 0 after user quit, 1 otherwise */ |
796 |
static int |
static int |
824 |
case ClientMessage: |
case ClientMessage: |
825 |
/* the window manager told us to quit */ |
/* the window manager told us to quit */ |
826 |
if ((xevent.xclient.message_type == protocol_atom) |
if ((xevent.xclient.message_type == protocol_atom) |
827 |
&& ((Atom)xevent.xclient.data.l[0] == kill_atom)) |
&& ((Atom) xevent.xclient.data.l[0] == kill_atom)) |
828 |
/* Quit */ |
/* Quit */ |
829 |
return 0; |
return 0; |
830 |
break; |
break; |
831 |
|
|
832 |
case KeyPress: |
case KeyPress: |
833 |
|
last_gesturetime = ((XKeyEvent *) & xevent)->time; |
834 |
if (IC != NULL) |
if (IC != NULL) |
835 |
/* Multi_key compatible version */ |
/* Multi_key compatible version */ |
836 |
{ |
{ |
871 |
break; |
break; |
872 |
|
|
873 |
case KeyRelease: |
case KeyRelease: |
874 |
|
last_gesturetime = ((XKeyEvent *) & xevent)->time; |
875 |
XLookupString((XKeyEvent *) & xevent, str, |
XLookupString((XKeyEvent *) & xevent, str, |
876 |
sizeof(str), &keysym, NULL); |
sizeof(str), &keysym, NULL); |
877 |
|
|
892 |
break; |
break; |
893 |
|
|
894 |
case ButtonPress: |
case ButtonPress: |
895 |
|
last_gesturetime = ((XButtonEvent *) & xevent)->time; |
896 |
flags = MOUSE_FLAG_DOWN; |
flags = MOUSE_FLAG_DOWN; |
897 |
/* fall through */ |
/* fall through */ |
898 |
|
|
899 |
case ButtonRelease: |
case ButtonRelease: |
900 |
|
last_gesturetime = ((XButtonEvent *) & xevent)->time; |
901 |
button = xkeymap_translate_button(xevent.xbutton.button); |
button = xkeymap_translate_button(xevent.xbutton.button); |
902 |
if (button == 0) |
if (button == 0) |
903 |
break; |
break; |
1033 |
mod_map = XGetModifierMapping(display); |
mod_map = XGetModifierMapping(display); |
1034 |
} |
} |
1035 |
break; |
break; |
1036 |
|
/* Clipboard stuff */ |
1037 |
|
case SelectionClear: |
1038 |
|
cliprdr_handle_SelectionClear(); |
1039 |
|
break; |
1040 |
|
case SelectionNotify: |
1041 |
|
cliprdr_handle_SelectionNotify((XSelectionEvent *) & xevent); |
1042 |
|
break; |
1043 |
|
case SelectionRequest: |
1044 |
|
cliprdr_handle_SelectionRequest((XSelectionRequestEvent *) & |
1045 |
|
xevent); |
1046 |
|
break; |
1047 |
|
|
1048 |
|
case PropertyNotify: |
1049 |
|
xwin_process_propertynotify((XPropertyEvent *) & xevent); |
1050 |
|
break; |
1051 |
|
|
1052 |
|
|
1053 |
} |
} |
1054 |
} |
} |
1194 |
scanline = (width + 7) / 8; |
scanline = (width + 7) / 8; |
1195 |
offset = scanline * height; |
offset = scanline * height; |
1196 |
|
|
1197 |
cursor = (uint8*)xmalloc(offset); |
cursor = (uint8 *) xmalloc(offset); |
1198 |
memset(cursor, 0, offset); |
memset(cursor, 0, offset); |
1199 |
|
|
1200 |
mask = (uint8*)xmalloc(offset); |
mask = (uint8 *) xmalloc(offset); |
1201 |
memset(mask, 0, offset); |
memset(mask, 0, offset); |
1202 |
|
|
1203 |
/* approximate AND and XOR masks with a monochrome X pointer */ |
/* approximate AND and XOR masks with a monochrome X pointer */ |
1276 |
int i, ncolours = colours->ncolours; |
int i, ncolours = colours->ncolours; |
1277 |
if (!owncolmap) |
if (!owncolmap) |
1278 |
{ |
{ |
1279 |
uint32 *map = (uint32*)xmalloc(sizeof(*colmap) * ncolours); |
uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours); |
1280 |
XColor xentry; |
XColor xentry; |
1281 |
XColor xc_cache[256]; |
XColor xc_cache[256]; |
1282 |
uint32 colour; |
uint32 colour; |
1354 |
XColor *xcolours, *xentry; |
XColor *xcolours, *xentry; |
1355 |
Colormap map; |
Colormap map; |
1356 |
|
|
1357 |
xcolours = (XColor*)xmalloc(sizeof(XColor) * ncolours); |
xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours); |
1358 |
for (i = 0; i < ncolours; i++) |
for (i = 0; i < ncolours; i++) |
1359 |
{ |
{ |
1360 |
entry = &colours->colours[i]; |
entry = &colours->colours[i]; |
1384 |
ui_set_colourmap(HCOLOURMAP map) |
ui_set_colourmap(HCOLOURMAP map) |
1385 |
{ |
{ |
1386 |
if (!owncolmap) |
if (!owncolmap) |
1387 |
colmap = (uint32*)map; |
colmap = (uint32 *) map; |
1388 |
else |
else |
1389 |
XSetWindowColormap(display, wnd, (Colormap) map); |
XSetWindowColormap(display, wnd, (Colormap) map); |
1390 |
} |
} |
1429 |
} |
} |
1430 |
|
|
1431 |
static uint8 hatch_patterns[] = { |
static uint8 hatch_patterns[] = { |
1432 |
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */ |
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */ |
1433 |
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */ |
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */ |
1434 |
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */ |
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */ |
1435 |
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */ |
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */ |
1436 |
0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */ |
0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */ |
1437 |
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */ |
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */ |
1438 |
}; |
}; |
1439 |
|
|
1440 |
void |
void |
1455 |
break; |
break; |
1456 |
|
|
1457 |
case 2: /* Hatch */ |
case 2: /* Hatch */ |
1458 |
fill = (Pixmap) ui_create_glyph(8, 8, hatch_patterns + brush->pattern[0] * 8); |
fill = (Pixmap) ui_create_glyph(8, 8, |
1459 |
|
hatch_patterns + brush->pattern[0] * 8); |
1460 |
SET_FOREGROUND(bgcolour); |
SET_FOREGROUND(bgcolour); |
1461 |
SET_BACKGROUND(fgcolour); |
SET_BACKGROUND(fgcolour); |
1462 |
XSetFillStyle(display, gc, FillOpaqueStippled); |
XSetFillStyle(display, gc, FillOpaqueStippled); |
1757 |
|
|
1758 |
XFree(image); |
XFree(image); |
1759 |
} |
} |
1760 |
|
|
1761 |
|
|
1762 |
|
void |
1763 |
|
xwin_register_propertynotify(Window event_wnd, Atom atom, |
1764 |
|
void (*propertycallback) (XPropertyEvent *)) |
1765 |
|
{ |
1766 |
|
PropNotifyCb *this; |
1767 |
|
int window_already_registrered = 0; |
1768 |
|
if (NULL != propnotify_callbacks) |
1769 |
|
{ |
1770 |
|
this = propnotify_callbacks; |
1771 |
|
if (event_wnd == this->wnd) |
1772 |
|
{ |
1773 |
|
window_already_registrered = 1; |
1774 |
|
if (atom == this->atom) |
1775 |
|
return; |
1776 |
|
} |
1777 |
|
while (NULL != this->next) |
1778 |
|
{ |
1779 |
|
if (event_wnd == this->wnd) |
1780 |
|
{ |
1781 |
|
window_already_registrered = 1; |
1782 |
|
if (atom == this->atom) |
1783 |
|
return; |
1784 |
|
/* Find last entry in list */ |
1785 |
|
} |
1786 |
|
this = this->next; |
1787 |
|
} |
1788 |
|
this->next = xmalloc(sizeof(PropNotifyCb)); |
1789 |
|
this->next->next = NULL; |
1790 |
|
this = this->next; |
1791 |
|
|
1792 |
|
} |
1793 |
|
else |
1794 |
|
{ |
1795 |
|
this = xmalloc(sizeof(PropNotifyCb)); |
1796 |
|
this->next = NULL; |
1797 |
|
propnotify_callbacks = this; |
1798 |
|
} |
1799 |
|
if (!window_already_registrered) |
1800 |
|
{ |
1801 |
|
if (wnd == event_wnd) |
1802 |
|
XSelectInput(display, wnd, input_mask | PropertyChangeMask); |
1803 |
|
else |
1804 |
|
XSelectInput(display, event_wnd, PropertyChangeMask); |
1805 |
|
} |
1806 |
|
this->wnd = event_wnd; |
1807 |
|
this->atom = atom; |
1808 |
|
this->callback = propertycallback; |
1809 |
|
} |
1810 |
|
|
1811 |
|
|
1812 |
|
void |
1813 |
|
xwin_deregister_propertynotify(Window event_wnd, Atom atom) |
1814 |
|
{ |
1815 |
|
PropNotifyCb *this = propnotify_callbacks; |
1816 |
|
PropNotifyCb *prev; |
1817 |
|
int window_needed = 0; |
1818 |
|
prev = this; |
1819 |
|
while (NULL != this) |
1820 |
|
{ |
1821 |
|
if (event_wnd == this->wnd) |
1822 |
|
{ |
1823 |
|
if (atom == this->atom) |
1824 |
|
{ |
1825 |
|
if (prev == this) |
1826 |
|
{ |
1827 |
|
propnotify_callbacks = this->next; |
1828 |
|
} |
1829 |
|
else |
1830 |
|
{ |
1831 |
|
prev->next = this->next; |
1832 |
|
} |
1833 |
|
xfree(this); |
1834 |
|
continue; |
1835 |
|
} |
1836 |
|
else |
1837 |
|
{ |
1838 |
|
window_needed = 1; |
1839 |
|
} |
1840 |
|
} |
1841 |
|
prev = this; |
1842 |
|
this = this->next; |
1843 |
|
} |
1844 |
|
if (!window_needed) |
1845 |
|
{ |
1846 |
|
if (wnd != event_wnd) |
1847 |
|
{ |
1848 |
|
XSelectInput(display, event_wnd, NoEventMask); |
1849 |
|
} |
1850 |
|
else |
1851 |
|
{ |
1852 |
|
XSelectInput(display, wnd, input_mask); |
1853 |
|
} |
1854 |
|
} |
1855 |
|
} |