Back to index

im-sdk  12.3.91
xaux_ext_common.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 /*
00044  * Copyright (c) 1999 by Sun Microsystem, Inc.
00045  * All rights reserved.
00046  *
00047  * xaux_ext_common.c
00048  */
00049 
00050 /*
00051    Copyright (c) 2004 Yu Shao <yshao@redhat.com>
00052    Copyright (c) 1997-2004 Red Hat, Inc. All rights reserved.
00053 */
00054 
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058 #include <limits.h>
00059 
00060 #include <X11/X.h>
00061 #include <X11/Xatom.h>
00062 
00063 #include "iiimpAux.h"
00064 #include "xaux_common.h"
00065 #include "xaux_ext_common.h"
00066 
00067 static Bool xaux_xs_send_message();
00068 extern void DEBUG_printf(const char *format, ...);
00069 
00070 static Bool
00071 xaux_xs_get_sowin(
00072        xaux_class_t  *xc,
00073        Display              *display)
00074 {
00075        xc->sowin = XGetSelectionOwner(display, xc->atom_sowin);
00076 
00077        if (xc->sowin == None){
00078               return False;
00079        } else {
00080               return True;
00081         }
00082 }
00083 
00084 static Bool
00085 xaux_xs_send_property(
00086        Display *            display,
00087        xaux_class_t *              xc,
00088        int                  im_id,
00089        int                  ic_id,
00090        const unsigned char *       p,
00091        int                  len)
00092 {
00093        if (xaux_xs_get_sowin(xc, display) == False) {
00094               return False;
00095        }
00096 
00097        XChangeProperty(display, xc->sowin,
00098               xc->atom_xs[xc->atom_xs_idx], XA_STRING,
00099               8, PropModeReplace, (unsigned char *)p, len);
00100 
00101        if (xaux_xs_send_message(display, xc, im_id, ic_id,
00102               AUX_EXT_DATA_SETVALUE, xc->atom_xs[xc->atom_xs_idx]) == False) {
00103                      return False;
00104        }
00105 
00106        /* XFlush() has been called in xaux_xs_send_message() */
00107 
00108        if (++xc->atom_xs_idx == xc->atom_xs_num)
00109               xc->atom_xs_idx = 1;
00110        
00111        return True;
00112 }
00113 
00114 static Bool
00115 xaux_xs_send_message(
00116        Display *     display,
00117        xaux_class_t *       xc,
00118        int           im_id,
00119        int           ic_id,
00120        aux_ext_data_type_t  type,
00121        Atom          atom)
00122 {
00123        XClientMessageEvent  event;
00124 
00125        if ((xc->sowin == None) &&
00126               (xaux_xs_get_sowin(xc, display) == False)) {
00127               return False;
00128        }
00129               
00130        event.type = ClientMessage;
00131        event.serial = 0;
00132        event.send_event = True;
00133        event.display = display;
00134        event.window = xc->sowin;
00135        event.message_type = xc->atom_xs[0];
00136        event.format = 32;
00137 
00138        event.data.l[0] = xc->atom_classname;
00139        event.data.l[1] = ((CARD16)im_id << 8) | ((CARD16)ic_id & 0xffff);
00140        event.data.l[2] = xc->index;
00141        event.data.l[3] = type;
00142        if (type == AUX_EXT_DATA_SETVALUE) {
00143               event.data.l[4] = atom;
00144        } else {
00145               event.data.l[4] = 0; /* unused */
00146        }
00147 
00148        XSendEvent(display, xc->sowin, True, 0, (XEvent *)(&event));
00149 
00150        XFlush(display);
00151 
00152        return True;
00153 }
00154 
00155 static Bool
00156 xaux_ext_process_property_update(
00157        Display       *             display,
00158        Window               window,
00159        Atom                 atom)
00160 {
00161        Atom          actual_type_return;
00162        int           actual_format_return;
00163        unsigned long nitem_return;
00164        unsigned long bytes_after_return;
00165        unsigned char *      prop_return;
00166        int           r;
00167        int           i;
00168        Bool          rv;
00169        int           type;
00170        aux_ext_data_t       aux_ext_data_;
00171        aux_ext_data_t       *aux_ext_data = &(aux_ext_data_);
00172        xaux_class_t  *xc = &xaux_class;
00173 
00174        if (window != xc->extwin && window != xc->sowin) {
00175               return False;
00176        }
00177 
00178        r = XGetWindowProperty(display, window,
00179                             atom, 0, INT_MAX, False,
00180                             AnyPropertyType, &actual_type_return,
00181                             &actual_format_return, &nitem_return,
00182                             &bytes_after_return, &prop_return);
00183 
00184        if (r != Success || actual_type_return == 0) {
00185               return False;
00186        }
00187 
00188        type = SX_PROP_TYPE(prop_return);
00189 
00190        /* ClientMessage detoured to property, due to extwin not
00191           available yet */
00192        if (type == AUX_DATA_START || type == AUX_DATA_DONE) {
00193 
00194               if (SX_PROP_ATOM_AUX_NAME(prop_return) != xc->atom_classname) {
00195                      return False;
00196               }
00197 
00198               aux_ext_data->im = SX_PROP_IMID(prop_return);
00199               aux_ext_data->ic = SX_PROP_ICID(prop_return);
00200               aux_ext_data->aux_index = SX_PROP_INDEX(prop_return);
00201 
00202               switch (type) {
00203               case AUX_EXT_DATA_START:
00204                      DEBUG_printf("[%s] received START via property\n",
00205                             xc->classname);
00206                      //return xaux_ext_Start(xc, aux_ext_data);
00207                      break;
00208               case AUX_EXT_DATA_DONE:
00209                      DEBUG_printf("[%s] received DONE via property\n",
00210                             xc->classname);
00211                      //return xaux_ext_Done(xc, aux_ext_data);
00212                      break;
00213               default:
00214                      return False;
00215               }
00216        }
00217 
00218        /* header */
00219 
00220        aux_ext_data->type = AUX_EXT_DATA_DRAW;
00221        aux_ext_data->im = SX_PROP_IMID(prop_return);
00222        aux_ext_data->ic = SX_PROP_ICID(prop_return);
00223        aux_ext_data->aux_index = xc->index;
00224        aux_ext_data->aux_name = (unsigned char *)xc->classname;
00225        aux_ext_data->aux_name_length =
00226               strlen((const char *)aux_ext_data->aux_name);
00227 
00228        /* int values */
00229 
00230        aux_ext_data->integer_count = SX_PROP_INT_COUNT(prop_return);
00231 
00232        if (aux_ext_data->integer_count > 0) {
00233               aux_ext_data->integer_list =
00234                      (int *)SX_PROP_INT_LIST(prop_return);
00235        } else {
00236               aux_ext_data->integer_list = NULL;
00237        }
00238 
00239        /* string values */
00240 
00241        aux_ext_data->string_count = SX_PROP_STR_COUNT(prop_return);
00242 
00243        if (aux_ext_data->string_count > 0) {
00244               unsigned char * prop_str = SX_PROP_STR_LIST(prop_return);
00245 
00246               if ((aux_ext_data->string_list =
00247                      (aux_ext_string_t *)malloc(sizeof (aux_ext_string_t) *
00248                             aux_ext_data->string_count)) == NULL) {
00249                             XFree(prop_return);
00250                             return False;
00251               }
00252 
00253               for(i = 0; i < aux_ext_data->string_count; i++) {
00254                      char *        ib;
00255                      size_t        ibl;
00256 
00257                      /* assign length of a string to ibl */
00258                      ibl = (size_t)*((CARD16 *)(prop_str));
00259                      /* move prop_str to point head of the string */
00260                      prop_str += sizeof(CARD16);
00261                      /* assign head of the string to ib */
00262                      ib = (char *)prop_str;
00263                      /* move prop_str to point lenght of next string */
00264                      prop_str += (ibl + padding[(sizeof(CARD16) + ibl) % 4]);
00265 
00266                      aux_ext_data->string_list[i].ptr = (unsigned char *)ib;
00267                      aux_ext_data->string_list[i].length = ibl;
00268               }
00269        } else {
00270               aux_ext_data->string_list = NULL;
00271        }
00272 
00273        aux_ext_data->string_ptr = NULL;
00274 
00275        aux_ext_data->clientwin = SX_PROP_CLIENTWIN(prop_return);
00276        aux_ext_data->point.x = SX_PROP_POSX(prop_return);
00277        aux_ext_data->point.y = SX_PROP_POSY(prop_return);
00278        aux_ext_data->focuswin = SX_PROP_FOCUSWIN(prop_return);
00279 
00280        DEBUG_printf("[%s] received DRAW via property\n",
00281               xc->classname);
00282 
00283        rv = xaux_ext_Draw(xc, aux_ext_data);
00284 
00285        free(aux_ext_data->string_list);
00286        XFree(prop_return);
00287 
00288        return rv;
00289 }
00290 
00291 Bool
00292 xaux_ext_process_client_message(
00293        Display       *             display,
00294        XClientMessageEvent *       event)
00295 {
00296        aux_ext_data_t       aux_ext_data_;
00297        aux_ext_data_t       *aux_ext_data = &(aux_ext_data_);
00298        aux_ext_data_type_t  type;
00299        xaux_class_t  *xc = &xaux_class;
00300 
00301        if (event->data.l[0] != xc->atom_classname) {
00302               return False;
00303        }
00304 
00305        if (event->message_type != xc->atom_sx[0]) {
00306               return False;
00307        }
00308 
00309        if (event->window != xc->extwin) {
00310               return False;
00311        }
00312 
00313        aux_ext_data->im = ((CARD32)(event->data.l[1])) >> 16;
00314        aux_ext_data->ic = ((CARD32)(event->data.l[1])) & 0xffff;
00315        aux_ext_data->aux_index = (CARD32)(event->data.l[2]);
00316 
00317        type = (CARD32)(event->data.l[3]);
00318 
00319        switch (type) {
00320        case AUX_EXT_DATA_START:
00321               DEBUG_printf("[%s] received START via ClientMessage\n",
00322                      xc->classname);
00323               //return xaux_ext_Start(xc, aux_ext_data);
00324               break;
00325        case AUX_EXT_DATA_DRAW:
00326               DEBUG_printf("[%s] notified DRAW via ClientMessage\n",
00327                      xc->classname);
00328               return xaux_ext_process_property_update(
00329                      display, xc->extwin, (Atom)(CARD32)(event->data.l[4]));
00330        case AUX_EXT_DATA_DONE:
00331               DEBUG_printf("[%s] received DONE via ClientMessage\n",
00332                      xc->classname);
00333               return xaux_ext_Done(xc, aux_ext_data);
00334        default:
00335               return False;
00336        }
00337 
00338        return True;
00339 }
00340 
00341 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
00342 #define _NET_WM_STATE_ADD           1    /* add/set property */
00343 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
00344 
00345 /* To fix bug 4765026: input method has a window in task list of Gnome desktop */
00346 void xaux_ext_skip_taskbar_hint(Display *display, Window window, Bool add)
00347 {
00348        static Atom net_wm_state_skip_taskbar = (Atom)0;
00349 
00350        if (!net_wm_state_skip_taskbar) {
00351               net_wm_state_skip_taskbar = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", True);
00352        }
00353 
00354        if (net_wm_state_skip_taskbar != None) {
00355               XEvent xev;
00356               xev.xclient.type = ClientMessage;
00357               xev.xclient.serial = 0;
00358               xev.xclient.send_event = True;
00359               xev.xclient.window = window;
00360               xev.xclient.message_type = XInternAtom (display, "_NET_WM_STATE", True);
00361               xev.xclient.format = 32;
00362               xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
00363               xev.xclient.data.l[1] = net_wm_state_skip_taskbar;
00364               xev.xclient.data.l[2] = net_wm_state_skip_taskbar;
00365 
00366               XSendEvent (display, RootWindow(display, DefaultScreen(display)),
00367                             False,
00368                             SubstructureRedirectMask | SubstructureNotifyMask,
00369                             &xev);
00370        }
00371 }
00372 
00373 Bool
00374 xaux_ext_init_classes(
00375        Display              *display,
00376        xaux_class_t  *p,
00377        Window        extwin)
00378 {
00379        char          buf[1024];
00380        int           i;
00381 
00382        DEBUG_printf("xaux_ext_init_classes classname:%s, extwin:%d\n", p->classname, extwin);
00383        p->atom_classname = XInternAtom(display, p->classname, False);
00384 
00385        sprintf(buf, "%s%s", p->classname, XAUX_SOWIN_SUFFIX);
00386        p->atom_sowin = XInternAtom(display, buf, False);
00387 
00388 
00389        sprintf(buf, "%s%s", p->classname, XAUX_EXTWIN_SUFFIX);
00390        p->atom_extwin = XInternAtom(display, buf, False);
00391 
00392        for (i = 0; i < p->atom_sx_num; i++) {
00393               sprintf(buf, "%s%s_%d", p->classname, XAUX_SX_SUFFIX, i);
00394               p->atom_sx[i] = XInternAtom(display, buf, False);
00395        }
00396 
00397        p->atom_sx_idx = 1;
00398 
00399        for (i = 0; i < p->atom_xs_num; i++) {
00400               sprintf(buf, "%s%s_%d", p->classname, XAUX_XS_SUFFIX, i);
00401               p->atom_xs[i] = XInternAtom(display, buf, False);
00402        }
00403 
00404        p->atom_xs_idx = 1;
00405 
00406        p->sowin = (Window)0;
00407 
00408        p->extwin = extwin;
00409 
00410        if (XGetSelectionOwner(display, p->atom_extwin) != None) {
00411               DEBUG_printf("%s: %s already exists.[%s](1)\n",
00412                      ME_EXT, ME_EXT, p->classname);
00413               return False;
00414        }
00415 
00416        XSetSelectionOwner(display, p->atom_extwin, p->extwin, CurrentTime);
00417 
00418        if (XGetSelectionOwner(display, p->atom_extwin) != p->extwin) {
00419               DEBUG_printf("%s: %s already exists.[%s](2)\n",
00420                      ME_EXT, ME_EXT, p->classname);
00421               XDestroyWindow(display, p->extwin);
00422               p->extwin = (Window)0;
00423               return False;
00424        }
00425 
00426        /* process sx properties which has been put on sowin before
00427           extwin is prepared */
00428        if (xaux_xs_get_sowin(p, display) == True) {
00429               for (i = p->atom_sx_idx; i < p->atom_sx_num; i++) {
00430                      if (xaux_ext_process_property_update(
00431                             display, p->sowin, p->atom_sx[i]) == False) {
00432                             break;
00433                      }
00434               }
00435        }
00436        return True;
00437 }
00438 
00439 Bool
00440 xaux_ext_SetValue(
00441        Display              *display,
00442        xaux_class_t  *xc,
00443        aux_ext_data_t       *aux_ext_data)
00444 {
00445        static char   *string_buf = NULL;
00446        static size_t bufsize = 0;
00447        size_t        i;
00448        size_t        total = 0;
00449        int           *ip;
00450        char          *sp;
00451        Bool          rv = True;
00452 
00453        if (aux_ext_data == NULL) {
00454               /* reset; free string_buf */
00455               if (string_buf != NULL) {
00456                      free(string_buf);
00457                      string_buf = NULL;
00458               }
00459               bufsize = 0;
00460               return True;
00461        }
00462 
00463        total = XS_SIZE_PROP_HEADER_SETVALUE
00464               + (sizeof (CARD32) * aux_ext_data->integer_count);
00465 
00466        if (aux_ext_data->string_count > 0) {
00467               for (i = 0; i < aux_ext_data->string_count; i++) {
00468                      size_t len;
00469 
00470                      len = aux_ext_data->string_list[i].length
00471                             * sizeof (CARD16);
00472                      total += ((sizeof (CARD16) + len + 3) / 4) * 4;
00473               }
00474 
00475               /*
00476                * "+1" is required by mb_utf16() method.
00477                * The method uses the area for BOM.
00478                */
00479               total += sizeof (CARD16);
00480        }
00481 
00482        /* tentatively use realloc(); may replace with malloc() later */
00483        /* othewise, cleanup (freeing) routine should be provided */
00484        if (total > bufsize) {
00485               string_buf = realloc(string_buf, total);
00486               if (string_buf == NULL) {
00487                      bufsize = 0;
00488                      return False;
00489               }
00490               bufsize = total;
00491        }
00492 
00493        XS_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
00494        XS_PROP_IMID(string_buf) = aux_ext_data->im;
00495        XS_PROP_ICID(string_buf) = aux_ext_data->ic;
00496 
00497        XS_PROP_INT_COUNT(string_buf) = aux_ext_data->integer_count;
00498        XS_PROP_STR_COUNT(string_buf) = aux_ext_data->string_count;
00499 
00500 
00501        ip = (int *)XS_PROP_INT_LIST(string_buf);
00502 
00503        if (aux_ext_data->integer_count > 0) {
00504 
00505               for (i = 0; i < aux_ext_data->integer_count; i++) {
00506                      *ip++ = aux_ext_data->integer_list[i];
00507               }
00508        }
00509 
00510        sp = (char *)XS_PROP_STR_LIST(string_buf);
00511 
00512        if (aux_ext_data->string_count > 0) {
00513               char *        ob;
00514 
00515               ob = sp;
00516 
00517               for (i = 0; i < aux_ext_data->string_count; i++) {
00518                      size_t        len;
00519                      int           pn;
00520                      unsigned char *p;
00521                      size_t        j;
00522 
00523                      len = aux_ext_data->string_list[i].length;
00524                      p = aux_ext_data->string_list[i].ptr;
00525 
00526                      *(CARD16 *)ob = len;
00527                      ob += sizeof (CARD16);
00528 
00529                      for (j = 0; j < len; j++) {
00530                             *ob++ = *p++;
00531                      }
00532                             
00533                      pn = padding[(sizeof (CARD16) + len) % 4];
00534 
00535                      /* padding */
00536                      for (j = 0; j < pn; j++) {
00537                             *ob++ = 0U;
00538                      }
00539                      sp = ob;
00540               }
00541        }
00542 
00543        DEBUG_printf("ext_SetValue[%s] im:0x%x ic:0x%x in=%d sn=%d\n",
00544               xc->classname, aux_ext_data->im, aux_ext_data->ic,
00545               aux_ext_data->integer_count, aux_ext_data->string_count);
00546 
00547        if (aux_ext_data->integer_count != 0 ||
00548               aux_ext_data->string_count != 0) {
00549 
00550        DEBUG_printf("ext_SetValue will call send property\n");
00551               rv = xaux_xs_send_property(display, xc,
00552                      aux_ext_data->im, aux_ext_data->ic,
00553                      (unsigned char *)string_buf, (sp - &(string_buf[0])));
00554        }
00555 
00556        return (rv);
00557 }
00558