URI:
       tevent.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tevent.c (12295B)
       ---
            1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
            2 #include <stdio.h>
            3 #include <stdlib.h>
            4 #include <X11/X.h>
            5 #include <X11/Xos.h>
            6 #include <X11/Xlib.h>
            7 #include <X11/Xutil.h>
            8 #include <X11/Xatom.h>
            9 #include <X11/extensions/shape.h>
           10 #include "dat.h"
           11 #include "fns.h"
           12 #include "patchlevel.h"
           13 
           14 void
           15 mainloop(int shape_event)
           16 {
           17         XEvent ev;
           18 
           19         for(;;){
           20                 getevent(&ev);
           21 
           22 #ifdef        DEBUG_EV
           23                 if(debug){
           24                         ShowEvent(&ev);
           25                         printf("\n");
           26                 }
           27 #endif
           28                 switch (ev.type){
           29                 default:
           30 #ifdef        SHAPE
           31                         if(shape && ev.type == shape_event)
           32                                 shapenotify((XShapeEvent *)&ev);
           33                         else
           34 #endif
           35                                 fprintf(stderr, "rio: unknown ev.type %d\n", ev.type);
           36                         break;
           37                 case KeyPress:
           38                         keypress(&ev.xkey);
           39                         break;
           40                 case KeyRelease:
           41                         keyrelease(&ev.xkey);
           42                         break;
           43                 case ButtonPress:
           44                         button(&ev.xbutton);
           45                         break;
           46                 case ButtonRelease:
           47                         break;
           48                 case MapRequest:
           49                         mapreq(&ev.xmaprequest);
           50                         break;
           51                 case ConfigureRequest:
           52                         configurereq(&ev.xconfigurerequest);
           53                         break;
           54                 case CirculateRequest:
           55                         circulatereq(&ev.xcirculaterequest);
           56                         break;
           57                 case UnmapNotify:
           58                         unmap(&ev.xunmap);
           59                         break;
           60                 case CreateNotify:
           61                         newwindow(&ev.xcreatewindow);
           62                         break;
           63                 case DestroyNotify:
           64                         destroy(ev.xdestroywindow.window);
           65                         break;
           66                 case ClientMessage:
           67                         clientmesg(&ev.xclient);
           68                         break;
           69                 case ColormapNotify:
           70                         cmap(&ev.xcolormap);
           71                         break;
           72                 case PropertyNotify:
           73                         property(&ev.xproperty);
           74                         break;
           75                 case SelectionClear:
           76                         fprintf(stderr, "rio: SelectionClear (this should not happen)\n");
           77                         break;
           78                 case SelectionNotify:
           79                         fprintf(stderr, "rio: SelectionNotify (this should not happen)\n");
           80                         break;
           81                 case SelectionRequest:
           82                         fprintf(stderr, "rio: SelectionRequest (this should not happen)\n");
           83                         break;
           84                 case EnterNotify:
           85                         enter(&ev.xcrossing);
           86                         break;
           87                 case LeaveNotify:
           88                         leave(&ev.xcrossing);
           89                         break;
           90                 case ReparentNotify:
           91                         reparent(&ev.xreparent);
           92                         break;
           93                 case FocusIn:
           94                         focusin(&ev.xfocus);
           95                         break;
           96                 case MotionNotify:
           97                         motionnotify(&ev.xmotion);
           98                         break;
           99                 case Expose:
          100                 case NoExpose:
          101                 case FocusOut:
          102                 case ConfigureNotify:
          103                 case MapNotify:
          104                 case MappingNotify:
          105                 case GraphicsExpose:
          106                         /* not interested */
          107                         trace("ignore", 0, &ev);
          108                         break;
          109                 }
          110         }
          111 }
          112 
          113 
          114 void
          115 configurereq(XConfigureRequestEvent *e)
          116 {
          117         XWindowChanges wc;
          118         Client *c;
          119 
          120         /* we don't set curtime as nothing here uses it */
          121         c = getclient(e->window, 0);
          122         trace("configurereq", c, e);
          123 
          124         e->value_mask &= ~CWSibling;
          125 
          126         if(c){
          127                 if(e->value_mask & CWX)
          128                         c->x = e->x;
          129                 if(e->value_mask & CWY)
          130                         c->y = e->y;
          131                 if(e->value_mask & CWWidth)
          132                         c->dx = e->width;
          133                 if(e->value_mask & CWHeight)
          134                         c->dy = e->height;
          135                 if(e->value_mask & CWBorderWidth)
          136                         c->border = e->border_width;
          137 
          138                 if(c->dx >= c->screen->width && c->dy >= c->screen->height)
          139                         c->border = 0;
          140                 else
          141                         c->border = BORDER;
          142 
          143                 if(e->value_mask & CWStackMode){
          144                         if(e->detail == Above)
          145                                 top(c);
          146                         else
          147                                 e->value_mask &= ~CWStackMode;
          148                 }
          149                 e->value_mask |= CWX|CWY|CWHeight|CWWidth;
          150 
          151                 if(c->parent != c->screen->root && c->window == e->window){
          152                         wc.x = c->x - c->border;
          153                         wc.y = c->y - c->border;
          154                         wc.width = c->dx+c->border+c->border;
          155                         wc.height = c->dy+c->border+c->border;
          156                         wc.border_width = 1;
          157                         wc.sibling = None;
          158                         wc.stack_mode = e->detail;
          159                         XConfigureWindow(dpy, c->parent, e->value_mask, &wc);
          160 
          161                         if(e->value_mask & CWStackMode){
          162                                 top(c);
          163                                 active(c);
          164                         }
          165                 }
          166         }
          167 
          168         if(c && c->parent != c->screen->root){
          169                 wc.x = c->border;
          170                 wc.y = c->border;
          171         }else {
          172                 wc.x = c->x;
          173                 wc.y = c->y;
          174         }
          175         wc.width = c->dx;
          176         wc.height = c->dy;
          177         wc.border_width = 0;
          178         wc.sibling = None;
          179         wc.stack_mode = Above;
          180         e->value_mask &= ~CWStackMode;
          181         e->value_mask |= CWBorderWidth;
          182         XConfigureWindow(dpy, c->window, e->value_mask, &wc);
          183 }
          184 
          185 void
          186 mapreq(XMapRequestEvent *e)
          187 {
          188         Client *c;
          189         int i;
          190 
          191         curtime = CurrentTime;
          192         c = getclient(e->window, 0);
          193         trace("mapreq", c, e);
          194 
          195         if(c == 0 || c->window != e->window){
          196                 /* workaround for stupid NCDware */
          197                 fprintf(stderr, "rio: bad mapreq c %p w %x, rescanning\n",
          198                         (void*)c, (int)e->window);
          199                 for(i = 0; i < num_screens; i++)
          200                         scanwins(&screens[i]);
          201                 c = getclient(e->window, 0);
          202                 if(c == 0 || c->window != e->window){
          203                         fprintf(stderr, "rio: window not found after rescan\n");
          204                         return;
          205                 }
          206         }
          207 
          208         switch (c->state){
          209         case WithdrawnState:
          210                 if(c->parent == c->screen->root){
          211                         if(!manage(c, 0))
          212                                 return;
          213                         break;
          214                 }
          215                 XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
          216                 XAddToSaveSet(dpy, c->window);
          217                 /* fall through... */
          218         case NormalState:
          219                 XMapWindow(dpy, c->window);
          220                 XMapRaised(dpy, c->parent);
          221                 top(c);
          222                 setstate(c, NormalState);
          223                 if(c->trans != None && current && c->trans == current->window)
          224                                 active(c);
          225                 break;
          226         case IconicState:
          227                 unhidec(c, 1);
          228                 break;
          229         }
          230 }
          231 
          232 void
          233 unmap(XUnmapEvent *e)
          234 {
          235         Client *c;
          236 
          237         curtime = CurrentTime;
          238         c = getclient(e->window, 0);
          239         if(c){
          240                 switch (c->state){
          241                 case IconicState:
          242                         if(e->send_event){
          243                                 unhidec(c, 0);
          244                                 withdraw(c);
          245                         }
          246                         break;
          247                 case NormalState:
          248                         if(c == current)
          249                                 nofocus();
          250                         if(!c->reparenting)
          251                                 withdraw(c);
          252                         break;
          253                 }
          254                 c->reparenting = 0;
          255         }
          256 }
          257 
          258 void
          259 circulatereq(XCirculateRequestEvent *e)
          260 {
          261         fprintf(stderr, "It must be the warlock Krill!\n");  /* ☺ */
          262 }
          263 
          264 void
          265 newwindow(XCreateWindowEvent *e)
          266 {
          267         Client *c;
          268         ScreenInfo *s;
          269 
          270         /* we don't set curtime as nothing here uses it */
          271         if(e->override_redirect)
          272                 return;
          273         c = getclient(e->window, 1);
          274         if(c && c->window == e->window && (s = getscreen(e->parent))){
          275                 c->x = e->x;
          276                 c->y = e->y;
          277                 c->dx = e->width;
          278                 c->dy = e->height;
          279                 c->border = e->border_width;
          280                 c->screen = s;
          281                 if(c->parent == None)
          282                         c->parent = c->screen->root;
          283         }
          284 }
          285 
          286 void
          287 destroy(Window w)
          288 {
          289         int i;
          290         Client *c;
          291 
          292         curtime = CurrentTime;
          293         c = getclient(w, 0);
          294         if(c == 0)
          295                 return;
          296 
          297         if(numvirtuals > 1)
          298                 for(i=0; i<numvirtuals; i++)
          299                         if(currents[i] == c)
          300                                 currents[i] = 0;
          301 
          302         rmclient(c);
          303 
          304         /* flush any errors generated by the window's sudden demise */
          305         ignore_badwindow = 1;
          306         XSync(dpy, False);
          307         ignore_badwindow = 0;
          308 }
          309 
          310 void
          311 clientmesg(XClientMessageEvent *e)
          312 {
          313         Client *c;
          314 
          315         curtime = CurrentTime;
          316         if(e->message_type == exit_rio){
          317                 cleanup();
          318                 exit(0);
          319         }
          320         if(e->message_type == restart_rio){
          321                 fprintf(stderr, "*** rio restarting ***\n");
          322                 cleanup();
          323                 execvp(myargv[0], myargv);
          324                 perror("rio: exec failed");
          325                 exit(1);
          326         }
          327         if(e->message_type == wm_protocols)
          328                 return;
          329         if(e->message_type == wm_change_state){
          330                 c = getclient(e->window, 0);
          331                 if(e->format == 32 && e->data.l[0] == IconicState && c != 0){
          332                         if(normal(c))
          333                                 hide(c);
          334                 }
          335                 else
          336                         fprintf(stderr, "rio: WM_CHANGE_STATE: format %d data %d w 0x%x\n",
          337                                 (int)e->format, (int)e->data.l[0], (int)e->window);
          338                 return;
          339         }
          340         if(e->message_type == wm_state){
          341 //                c = getclient(e->window, 0);
          342 //                if(e->format == 32 && e->data.l[1] == wm_state_fullscreen){
          343 //                }else
          344                 fprintf(stderr, "rio: WM_STATE: format %d data %d %d w 0x%x\n",
          345                         (int)e->format, (int)e->data.l[0], (int)e->data.l[1],
          346                         (int)e->window);
          347                 return;
          348         }
          349         fprintf(stderr, "rio: strange ClientMessage, type 0x%x window 0x%x\n",
          350                 (int)e->message_type, (int)e->window);
          351 }
          352 
          353 void
          354 cmap(XColormapEvent *e)
          355 {
          356         Client *c;
          357         int i;
          358 
          359         /* we don't set curtime as nothing here uses it */
          360         if(e->new){
          361                 c = getclient(e->window, 0);
          362                 if(c){
          363                         c->cmap = e->colormap;
          364                         if(c == current)
          365                                 cmapfocus(c);
          366                 }
          367                 else
          368                         for(c = clients; c; c = c->next){
          369                                 for(i = 0; i < c->ncmapwins; i++)
          370                                         if(c->cmapwins[i] == e->window){
          371                                                 c->wmcmaps[i] = e->colormap;
          372                                                 if(c == current)
          373                                                         cmapfocus(c);
          374                                                 return;
          375                                         }
          376                         }
          377         }
          378 }
          379 
          380 void
          381 property(XPropertyEvent *e)
          382 {
          383         Atom a;
          384         int delete;
          385         Client *c;
          386         long msize;
          387 
          388         /* we don't set curtime as nothing here uses it */
          389         a = e->atom;
          390         delete = (e->state == PropertyDelete);
          391         c = getclient(e->window, 0);
          392         if(c == 0)
          393                 return;
          394 
          395         switch (a){
          396         case XA_WM_ICON_NAME:
          397                 if(c->iconname != 0)
          398                         XFree((char*) c->iconname);
          399                 c->iconname = delete ? 0 : getprop(c->window, a);
          400                 setlabel(c);
          401                 renamec(c, c->label);
          402                 return;
          403         case XA_WM_NAME:
          404                 if(c->name != 0)
          405                         XFree((char*) c->name);
          406                 c->name = delete ? 0 : getprop(c->window, a);
          407                 setlabel(c);
          408                 renamec(c, c->label);
          409                 return;
          410         case XA_WM_TRANSIENT_FOR:
          411                 gettrans(c);
          412                 return;
          413         case XA_WM_HINTS:
          414         case XA_WM_SIZE_HINTS:
          415         case XA_WM_ZOOM_HINTS:
          416                 /* placeholders to not forget.  ignore for now.  -Axel */
          417                 return;
          418         case XA_WM_NORMAL_HINTS:
          419                 if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
          420                         c->size.flags = PSize;        /* not specified - punt */
          421                 return;
          422         }
          423         if(a == _rio_hold_mode){
          424                 c->hold = getiprop(c->window, _rio_hold_mode);
          425                 if(c == current)
          426                         draw_border(c, 1);
          427         }
          428         else if(a == wm_colormaps){
          429                 getcmaps(c);
          430                 if(c == current)
          431                         cmapfocus(c);
          432         }
          433 }
          434 
          435 void
          436 reparent(XReparentEvent *e)
          437 {
          438         Client *c;
          439         XWindowAttributes attr;
          440         ScreenInfo *s;
          441 
          442         /* we don't set curtime as nothing here uses it */
          443         if(!getscreen(e->event) || e->override_redirect)
          444                 return;
          445         if((s = getscreen(e->parent)) != 0){
          446                 c = getclient(e->window, 1);
          447                 if(c != 0 && (c->dx == 0 || c->dy == 0)){
          448                         /* flush any errors */
          449                         ignore_badwindow = 1;
          450                         XGetWindowAttributes(dpy, c->window, &attr);
          451                         XSync(dpy, False);
          452                         ignore_badwindow = 0;
          453 
          454                         c->x = attr.x;
          455                         c->y = attr.y;
          456                         c->dx = attr.width;
          457                         c->dy = attr.height;
          458                         c->border = attr.border_width;
          459                         c->screen = s;
          460                         if(c->parent == None)
          461                                 c->parent = c->screen->root;
          462                 }
          463         }
          464         else {
          465                 c = getclient(e->window, 0);
          466                 if(c != 0 && (c->parent == c->screen->root || withdrawn(c)))
          467                         rmclient(c);
          468         }
          469 }
          470 
          471 #ifdef        SHAPE
          472 void
          473 shapenotify(XShapeEvent *e)
          474 {
          475         Client *c;
          476 
          477         /* we don't set curtime as nothing here uses it */
          478         c = getclient(e->window, 0);
          479         if(c == 0)
          480                 return;
          481 
          482         setshape(c);
          483 }
          484 #endif
          485 
          486 void
          487 enter(XCrossingEvent *e)
          488 {
          489         Client *c;
          490 
          491         curtime = e->time;
          492         if(!ffm)
          493         if(e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual)
          494                 return;
          495         c = getclient(e->window, 0);
          496         if(c != 0 && c != current){
          497                 /* someone grabbed the pointer; make them current */
          498                 if(!ffm)
          499                         XMapRaised(dpy, c->parent);
          500                 top(c);
          501                 active(c);
          502         }
          503 }
          504 
          505 void
          506 leave(XCrossingEvent *e)
          507 {
          508         Client *c;
          509 
          510         c = getclient(e->window, 0);
          511         if(c)
          512                 XUndefineCursor(dpy, c->parent);
          513 /*         XDefineCursor(dpy, c->parent, c->screen->arrow); */
          514 }
          515 
          516 void
          517 focusin(XFocusChangeEvent *e)
          518 {
          519         Client *c;
          520 
          521         curtime = CurrentTime;
          522         if(e->detail != NotifyNonlinearVirtual)
          523                 return;
          524         c = getclient(e->window, 0);
          525         if(c != 0 && c->window == e->window && c != current){
          526                 /* someone grabbed keyboard or seized focus; make them current */
          527                 XMapRaised(dpy, c->parent);
          528                 top(c);
          529                 active(c);
          530         }
          531 }
          532 
          533 BorderOrient
          534 borderorient(Client *c, int x, int y)
          535 {
          536         if(x <= BORDER){
          537                 if(y <= CORNER){
          538                         if(debug) fprintf(stderr, "topleft\n");
          539                         return BorderWNW;
          540                 }
          541                 if(y >= (c->dy + 2*BORDER) - CORNER){
          542                         if(debug) fprintf(stderr, "botleft\n");
          543                         return BorderWSW;
          544                 }
          545                 if(y > CORNER &&
          546                         y < (c->dy + 2*BORDER) - CORNER){
          547                         if(debug) fprintf(stderr, "left\n");
          548                         return BorderW;
          549                 }
          550         } else if(x <= CORNER){
          551                 if(y <= BORDER){
          552                         if(debug) fprintf(stderr, "topleft\n");
          553                         return BorderNNW;
          554                 }
          555                 if  (y >= (c->dy + BORDER)){
          556                         if(debug) fprintf(stderr, "botleft\n");
          557                         return BorderSSW;
          558                 }
          559         } else if(x >= (c->dx + BORDER)){
          560                 if(y <= CORNER){
          561                         if(debug) fprintf(stderr, "topright\n");
          562                         return BorderENE;
          563                 }
          564                 if(y >= (c->dy + 2*BORDER) - CORNER){
          565                         if(debug) fprintf(stderr, "botright\n");
          566                         return BorderESE;
          567                 }
          568                 if(y > CORNER &&
          569                         y < (c->dy + 2*BORDER) - CORNER){
          570                         if(debug) fprintf(stderr, "right\n");
          571                         return BorderE;
          572                 }
          573         } else if(x >= (c->dx + 2*BORDER) - CORNER){
          574                 if(y <= BORDER){
          575                         if(debug) fprintf(stderr, "topright\n");
          576                         return BorderNNE;
          577                 }
          578                 if  (y >= (c->dy + BORDER)){
          579                         if(debug) fprintf(stderr, "botright\n");
          580                         return BorderSSE;
          581                 }
          582         } else if(x > CORNER &&
          583                         x < (c->dx + 2*BORDER) - CORNER){
          584                 if(y <= BORDER){
          585                         if(debug) fprintf(stderr, "top\n");
          586                         return BorderN;
          587                 }
          588                 if(y >= (c->dy + BORDER)){
          589                         if(debug) fprintf(stderr, "bot\n");
          590                         return BorderS;
          591                 }
          592         }
          593         return BorderUnknown;
          594 }
          595 
          596 void
          597 motionnotify(XMotionEvent *e)
          598 {
          599         Client *c;
          600         BorderOrient bl;
          601 
          602         c = getclient(e->window, 0);
          603         if(c){
          604                 bl = borderorient(c, e->x, e->y);
          605                 if(bl == BorderUnknown)
          606                         XUndefineCursor(dpy, c->parent);
          607                 else
          608                         XDefineCursor(dpy, c->parent, c->screen->bordcurs[bl]);
          609         }
          610 }