/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 50 by matthewc, Sat Apr 20 09:41:03 2002 UTC revision 52 by n-ki, Fri Apr 26 08:22:39 2002 UTC
# Line 2  Line 2 
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-2001     Copyright (C) Matthew Chapman 1999-2001
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <X11/XKBlib.h>
24  #include <time.h>  #include <time.h>
25  #include <errno.h>  #include <errno.h>
26  #include "rdesktop.h"  #include "rdesktop.h"
# Line 32  extern BOOL sendmotion; Line 33  extern BOOL sendmotion;
33  extern BOOL fullscreen;  extern BOOL fullscreen;
34    
35  Display *display;  Display *display;
36    XkbDescPtr xkb;
37  static int x_socket;  static int x_socket;
38  static Window wnd;  static Window wnd;
39  static GC gc;  static GC gc;
# Line 47  static BOOL xserver_be; Line 49  static BOOL xserver_be;
49  static BOOL ownbackstore;  static BOOL ownbackstore;
50  static Pixmap backstore;  static Pixmap backstore;
51    
52    /* needed to keep track of the modifiers */
53    static unsigned int key_modifier_state = 0;
54    static unsigned int key_down_state = 0;
55    
56    #define DShift1Mask   (1<<0)
57    #define DShift2Mask   (1<<1)
58    #define DControl1Mask (1<<2)
59    #define DControl2Mask (1<<3)
60    #define DMod1Mask     (1<<4)
61    #define DMod2Mask     (1<<5)
62    
63  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
64  { \  { \
65          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(display, wnd, gc, x, y, cx, cy); \
# Line 86  static int rop2_map[] = { Line 99  static int rop2_map[] = {
99  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
100  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
101    
102    void xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);
103    void xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);
104    
105  static void  static void
106  translate8(uint8 *data, uint8 *out, uint8 *end)  translate8(uint8 *data, uint8 *out, uint8 *end)
107  {  {
# Line 191  ui_create_window(char *title) Line 207  ui_create_window(char *title)
207          Screen *screen;          Screen *screen;
208          uint16 test;          uint16 test;
209          int i;          int i;
210            
211            int xkb_minor, xkb_major;
212            int xkb_event, xkb_error, xkb_reason;
213    
214            /* compare compiletime libs with runtime libs. */
215            xkb_major = XkbMajorVersion;
216            xkb_minor = XkbMinorVersion;
217            if( XkbLibraryVersion( &xkb_major, &xkb_minor ) == False )
218            {
219                    error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");
220                    return False;
221            }
222    
223    
224            /* XKB is the 'new' keyboard handler in x.. ( the xkb code in Xfree86 originates from SGI, years 1993 and 1995 from what I could tell. )
225             * it makes it possible for people with disabilities to use rdesktop, stickykeys, bouncekeys etc. VERY MUCH useful.
226             * XFree86 has had support for it since it's earliest incarnation. I believe it is a reasonable dependency.
227             */
228            display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );
229            switch(xkb_reason)
230            {
231                    case XkbOD_BadLibraryVersion:
232                            error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");
233                            break;
234                    case XkbOD_ConnectionRefused:
235                            error("XkbOD_ConnectionRefused\n");
236                            break;
237                    case XkbOD_BadServerVersion:
238                            error("XkbOD_BadServerVersion\n");
239                            break;
240                    case XkbOD_NonXkbServer:
241                            error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");
242                            break;
243                    case XkbOD_Success:
244                            DEBUG("XkbOD_Success: Connection established with display\n");
245                            break;
246            }
247    
         display = XOpenDisplay(NULL);  
248          if (display == NULL)          if (display == NULL)
249          {          {
250                  error("Failed to open display\n");                  error("Failed to open display\n");
# Line 203  ui_create_window(char *title) Line 255  ui_create_window(char *title)
255          screen = DefaultScreenOfDisplay(display);          screen = DefaultScreenOfDisplay(display);
256          visual = DefaultVisualOfScreen(screen);          visual = DefaultVisualOfScreen(screen);
257          depth = DefaultDepthOfScreen(screen);          depth = DefaultDepthOfScreen(screen);
258            
259          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(display, &i);
260          if (pfm != NULL)          if (pfm != NULL)
261          {          {
# Line 284  ui_create_window(char *title) Line 336  ui_create_window(char *title)
336    
337          xkeymap_init();          xkeymap_init();
338    
339          input_mask = KeyPressMask | KeyReleaseMask          input_mask = KeyPressMask | KeyReleaseMask |
340                          | ButtonPressMask | ButtonReleaseMask                           ButtonPressMask | ButtonReleaseMask |
341                          | EnterWindowMask | LeaveWindowMask;                           EnterWindowMask | LeaveWindowMask | KeymapStateMask;
   
342          if (sendmotion)          if (sendmotion)
343                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
344    
# Line 301  ui_create_window(char *title) Line 352  ui_create_window(char *title)
352                  backstore = XCreatePixmap(display, wnd, width, height, depth);                  backstore = XCreatePixmap(display, wnd, width, height, depth);
353    
354          XMapWindow(display, wnd);          XMapWindow(display, wnd);
355    
356            /* TODO: error texts... make them friendly. */
357            xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);
358            if ((int)xkb == BadAlloc || xkb == NULL)
359            {
360                            error( "XkbGetKeyboard failed.\n");
361                            exit(0);
362            }
363    
364            /* TODO: error texts... make them friendly. */
365            if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )
366            {
367                            error( "XkbSelectEvents failed.\n");
368                            exit(0);
369            }
370    
371          return True;          return True;
372  }  }
373    
374  void  void
375  ui_destroy_window()  ui_destroy_window()
376  {  {
377            if( xkb != NULL )
378                    XkbFreeKeyboard(xkb, XkbAllControlsMask, True);
379    
380          if (ownbackstore)          if (ownbackstore)
381                  XFreePixmap(display, backstore);                  XFreePixmap(display, backstore);
382    
# Line 319  ui_destroy_window() Line 389  ui_destroy_window()
389  static void  static void
390  xwin_process_events()  xwin_process_events()
391  {  {
392          XEvent event;          XkbEvent xkbevent;
393            
394          KeySym keysym;          KeySym keysym;
395          uint8 scancode;          uint8 scancode;
396          uint16 button, flags;          uint16 button, flags;
397          uint32 ev_time;          uint32 ev_time;
398            uint32 tmpmods;
399    
400          if (display == NULL)          if (display == NULL)
401                  return;                  return;
402    
403          while (XCheckMaskEvent(display, ~0, &event))          while (XCheckMaskEvent(display, ~0, &xkbevent.core))
404          {          {
405                  ev_time = time(NULL);                  ev_time = time(NULL);
406                  flags = 0;                  flags = 0;
407    
408                  switch (event.type)                  switch (xkbevent.type)
409                  {                  {
410                            case KeymapNotify:
411                                    /* TODO:
412                                     * read modifier status at focus in, and update the local masks, and the other end as well..
413                                     * if not, we may get out of sync.
414                                     * xkbevent.core.xkeymap.key_vector
415                                     * char key_vector[32];
416                                     */
417                                    break;
418    
419                          case KeyRelease:                          case KeyRelease:
420                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
421                                  /* fall through */                                  /* fall through */
422    
423                          case KeyPress:                          case KeyPress:
424                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )
                                 scancode = xkeymap_translate_key(keysym, event.xkey.keycode, &flags);  
                                 if (scancode == 0)  
425                                          break;                                          break;
426                                    scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);
427    
428                                    if (scancode == 0 )
429                                            break;
430    
431                                    /* keep track of the modifiers -- needed for stickykeys... */
432                                    if( xkbevent.type == KeyPress )
433                                            xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );
434    
435                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
436    
437                                    if( xkbevent.type == KeyRelease )
438                                            xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );
439    
440                                  break;                                  break;
441    
442                          case ButtonPress:                          case ButtonPress:
# Line 353  xwin_process_events() Line 444  xwin_process_events()
444                                  /* fall through */                                  /* fall through */
445    
446                          case ButtonRelease:                          case ButtonRelease:
447                                  button = xkeymap_translate_button(event.xbutton.button);                                  button = xkeymap_translate_button(xkbevent.core.xbutton.button);
448                                  if (button == 0)                                  if (button == 0)
449                                          break;                                          break;
450    
451                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
452                                                 flags | button,                                                 flags | button,
453                                                 event.xbutton.x,                                                 xkbevent.core.xbutton.x,
454                                                 event.xbutton.y);                                                 xkbevent.core.xbutton.y);
455                                  break;                                  break;
456    
457                          case MotionNotify:                          case MotionNotify:
458                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
459                                                 MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE,
460                                                 event.xmotion.x,                                                 xkbevent.core.xmotion.x,
461                                                 event.xmotion.y);                                                 xkbevent.core.xmotion.y);
462                                  break;                                  break;
463    
464                          case EnterNotify:                          case EnterNotify:
# Line 381  xwin_process_events() Line 472  xwin_process_events()
472    
473                          case Expose:                          case Expose:
474                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(display, backstore, wnd, gc,
475                                            event.xexpose.x, event.xexpose.y,                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,
476                                            event.xexpose.width, event.xexpose.height,                                            xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,
477                                            event.xexpose.x, event.xexpose.y);                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);
478                                  break;                                  break;
479                  }                  }
480          }          }
481  }  }
482    
483  void  void
484    xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
485    {
486            switch (scancode) {
487            case 0x2a:
488                    key_down_state &= ~DShift1Mask;
489                    break;
490            case 0x36:
491                    key_down_state &= ~DShift2Mask;
492                    break;
493            case 0x1d:
494                    key_down_state &= ~DControl1Mask;
495                    break;
496            case 0x9d:
497                    key_down_state &= ~DControl2Mask;
498                    break;
499            case 0x38:
500                    key_down_state &= ~DMod1Mask;
501                    break;
502            case 0xb8:
503                    key_down_state &= ~DMod2Mask;
504                    break;
505            }
506    
507            if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))
508            {
509                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);
510                    key_down_state &= ~DShift1Mask;
511    
512            }
513    
514            if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))
515            {
516                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);
517                    key_down_state &= ~DControl1Mask;
518    
519            }
520            
521            if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))
522            {
523                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);
524                    key_down_state &= ~DMod1Mask;
525    
526            }
527            
528            if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))
529            {
530                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);
531                    key_down_state &= ~DMod2Mask;
532            }
533    }
534    
535    
536    void
537    xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
538    {
539            key_modifier_state = ev->state;
540    
541            switch (scancode) {
542            case 0x2a:
543                    key_down_state |= DShift1Mask;
544                    break;
545            case 0x36:
546                    key_down_state |= DShift2Mask;
547                    break;
548            case 0x1d:
549                    key_down_state |= DControl1Mask;
550                    break;
551            case 0x9d:
552                    key_down_state |= DControl2Mask;
553                    break;
554            case 0x38:
555                    key_down_state |= DMod1Mask;
556                    break;
557            case 0xb8:
558                    key_down_state |= DMod2Mask;
559                    break;
560            }
561    
562            if( (ShiftMask & ev->state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))
563            {
564                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);
565                    key_down_state |= DShift1Mask;
566    
567            }
568    
569            if( (ControlMask & ev->state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))
570            {
571                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);
572                    key_down_state |= DControl1Mask;
573    
574            }
575    
576            if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))
577            {
578                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);
579                    key_down_state |= DMod1Mask;
580    
581            }
582    
583            if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))
584            {
585                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);
586                    key_down_state |= DMod2Mask;
587    
588            }
589    }
590    
591    void
592  ui_select(int rdp_socket)  ui_select(int rdp_socket)
593  {  {
594          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
# Line 923  ui_draw_text(uint8 font, uint8 flags, in Line 1122  ui_draw_text(uint8 font, uint8 flags, in
1122                          if (entry != NULL) {                          if (entry != NULL) {
1123                                  if ((((uint8 *) (entry->data))[1] == 0)                                  if ((((uint8 *) (entry->data))[1] == 0)
1124                                      && (!(flags & TEXT2_IMPLICIT_X))) {                                      && (!(flags & TEXT2_IMPLICIT_X))) {
1125                                          if (flags & TEXT2_VERTICAL)                                                if (flags & TEXT2_VERTICAL)
1126                                                  y += text[i + 2];                                                  y += text[i + 2];
1127                                          else                                          else
1128                                                  x += text[i + 2];                                                  x += text[i + 2];
# Line 932  ui_draw_text(uint8 font, uint8 flags, in Line 1131  ui_draw_text(uint8 font, uint8 flags, in
1131                                          i += 3;                                          i += 3;
1132                                  else                                  else
1133                                          i += 2;                                          i += 2;
1134                                  length -= i;                                    length -= i;
1135                                  /* this will move pointer from start to first character after FE command */                                  /* this will move pointer from start to first character after FE command */
1136                                  text = &(text[i]);                                  text = &(text[i]);
1137                                  i = 0;                                  i = 0;

Legend:
Removed from v.50  
changed lines
  Added in v.52

  ViewVC Help
Powered by ViewVC 1.1.26