Back to index

im-sdk  12.3.91
xaux_ext_common.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <limits.h>
00003 #include <iconv.h>
00004 
00005 #include <X11/Xmd.h>
00006 #include <X11/Xlib.h>
00007 #include <X11/Xatom.h>
00008 
00009 #include "xaux_common.h"
00010 #include "xaux_ext_common.h"
00011 
00012 #include "aux-message.h"
00013 
00014 
00015 static Bool xaux_ext_get_sowin(xaux_class_t *xc, Display *display);
00016 static Bool xaux_ext_process_property_update(Display *display, Window window, Atom message_type, Atom atom);
00017 
00018 static aux_ext_data_t* convertAuxExtData(aux_ext_data_t* src, int Utf82Utf16)
00019 {
00020     static iconv_t ic16_8 = (iconv_t)-1;
00021     static iconv_t ic8_16 = (iconv_t)-1;
00022 
00023     int i, sz;
00024     char* sp, *dp;
00025     size_t srclen, dstlen;
00026 
00027     aux_ext_data_t* dst = (aux_ext_data_t*) malloc (sizeof(aux_ext_data_t));
00028 
00029     if (ic16_8 == (iconv_t)-1) ic16_8 = iconv_open("UTF-8", "UTF-16");
00030     if (ic8_16 == (iconv_t)-1) ic8_16 = iconv_open("UTF-16", "UTF-8");
00031 
00032 
00033     *dst = *src;
00034     dst->string_ptr = NULL;
00035     dst->string_list = NULL;
00036     if (dst->string_count) {
00037         dst->string_list = (aux_ext_string_t*)calloc(dst->string_count, sizeof(aux_ext_string_t));
00038 
00039         for (i=0; i < dst->string_count; ++i) {
00040             srclen = sz = src->string_list[i].length;
00041             sz = (sz+1)*((Utf82Utf16)?2:3);
00042             dst->string_list[i].ptr = (char*)malloc(sz);
00043             memset(dst->string_list[i].ptr, 0, sz);
00044 
00045             sp = src->string_list[i].ptr;
00046             dp = dst->string_list[i].ptr;
00047             dstlen = sz;
00048             if (Utf82Utf16) {
00049                 iconv(ic8_16, &sp, &srclen, &dp, &dstlen);
00050             } else {
00051                 iconv(ic16_8, &sp, &srclen, &dp, &dstlen);
00052             }
00053             dst->string_list[i].length = sz - dstlen;
00054         }
00055     }
00056 
00057     return dst;
00058 }
00059 
00060 static freeConvertedAuxExtData(aux_ext_data_t* dst)
00061 {
00062     int i;
00063     if (dst) {
00064         if (dst->string_list) {
00065             for (i=0; i < dst->string_count; ++i) {
00066                 if (dst->string_list[i].ptr)
00067                     free(dst->string_list[i].ptr);
00068             }
00069             free(dst->string_list);
00070         }
00071         free(dst);
00072     }
00073 }
00074 
00075 /************************************************************
00076     functions to process xaux_class_t and aux messages
00077 ************************************************************/
00078 Bool
00079 xaux_ext_init_classes(
00080         Display             *display,
00081         xaux_class_t *p,
00082         Window              extwin)
00083 {
00084         char         buf[1024];
00085         int          i;
00086 
00087         DEBUG_printf("xaux_ext_init_classes classname:%s, extwin:%d\n", p->classname, extwin);
00088 
00089         p->atom_classname = XInternAtom(display, p->classname, False);
00090 
00091 /*
00092         sprintf(buf, "%s%s", p->classname, XAUX_SOWIN_SUFFIX);
00093 */
00094         sprintf(buf, "%s", XAUX_OBJECT_CLASS_NAME);
00095         p->atom_sowin = XInternAtom(display, buf, False);
00096 
00097         sprintf(buf, "%s%s", p->classname, XAUX_EXTWIN_SUFFIX);
00098         p->atom_extwin = XInternAtom(display, buf, False);
00099 
00100         for (i = 0; i < p->atom_sx_num; i++) {
00101                 sprintf(buf, "%s%s_%d", p->classname, XAUX_SX_SUFFIX, i);
00102                 p->atom_sx[i] = XInternAtom(display, buf, False);
00103         }
00104 
00105         p->atom_sx_idx = 1;
00106 
00107         for (i = 0; i < p->atom_xs_num; i++) {
00108                 sprintf(buf, "%s%s_%d", p->classname, XAUX_XS_SUFFIX, i);
00109                 p->atom_xs[i] = XInternAtom(display, buf, False);
00110         }
00111 
00112         p->atom_xs_idx = 1;
00113 
00114         p->sowin = (Window)0;
00115 
00116         p->extwin = extwin;
00117 
00118         if (XGetSelectionOwner(display, p->atom_extwin) != None) {
00119                 DEBUG_printf("%s: %s already exists.[%s](1)\n",
00120                         ME_EXT, ME_EXT, p->classname);
00121                 return False;
00122         }
00123 
00124         XSetSelectionOwner(display, p->atom_extwin, p->extwin, CurrentTime);
00125 
00126         if (XGetSelectionOwner(display, p->atom_extwin) != p->extwin) {
00127                 DEBUG_printf("%s: %s already exists.[%s](2)\n",
00128                         ME_EXT, ME_EXT, p->classname);
00129                 XDestroyWindow(display, p->extwin);
00130                 p->extwin = (Window)0;
00131                 return False;
00132         }
00133 
00134         /* process sx properties which has been put on sowin before
00135            extwin is prepared */
00136         if (xaux_ext_get_sowin(p, display) == True) {
00137                 for (i = p->atom_sx_idx; i < p->atom_sx_num; i++) {
00138                         if (xaux_ext_process_property_update(
00139                                 display, p->sowin, p->atom_sx[i], p->atom_sx[i]) == False) {
00140                                 break;
00141                         }
00142                 }
00143         }
00144         return True;
00145 }
00146 
00147 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
00148 #define _NET_WM_STATE_ADD           1    /* add/set property */
00149 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
00150 
00151 /* To fix bug 4765026: input method has a window in task list of Gnome desktop */
00152 void xaux_ext_skip_taskbar_hint(Display *display, Window window, Bool add)
00153 {
00154         static Atom net_wm_state_skip_taskbar = (Atom)0;
00155 
00156         if (!net_wm_state_skip_taskbar) {
00157                 net_wm_state_skip_taskbar = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", True);
00158         }
00159 
00160         if (net_wm_state_skip_taskbar != None) {
00161                 XEvent xev;
00162                 xev.xclient.type = ClientMessage;
00163                 xev.xclient.serial = 0;
00164                 xev.xclient.send_event = True;
00165                 xev.xclient.window = window;
00166                 xev.xclient.message_type = XInternAtom (display, "_NET_WM_STATE", True);
00167                 xev.xclient.format = 32;
00168                 xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
00169                 xev.xclient.data.l[1] = net_wm_state_skip_taskbar;
00170                 xev.xclient.data.l[2] = net_wm_state_skip_taskbar;
00171 
00172                 XSendEvent (display, RootWindow(display, DefaultScreen(display)),
00173                                 False,
00174                                 SubstructureRedirectMask | SubstructureNotifyMask,
00175                                 &xev);
00176         }
00177 }
00178 
00179 static Bool
00180 xaux_ext_get_sowin(
00181         xaux_class_t *xc,
00182         Display             *display)
00183 {
00184         xc->sowin = XGetSelectionOwner(display, xc->atom_sowin);
00185 
00186         if (xc->sowin == None)
00187                 return False;
00188         else
00189                 return True;
00190 }
00191 
00192 static char *xaux_ext_compose_aux_ext_data(xaux_class_t *xc, aux_ext_data_t *aux_ext_data, int *string_len)
00193 {
00194         char  *string_buf = NULL;
00195         size_t       i;
00196         size_t       total = 0;
00197         int   *ip;
00198         char  *sp;
00199         Bool  rv = True;
00200 
00201         total = XS_SIZE_PROP_HEADER_SETVALUE
00202                 + (sizeof (CARD32) * aux_ext_data->integer_count);
00203 
00204         if (aux_ext_data->string_count > 0) {
00205                 for (i = 0; i < aux_ext_data->string_count; i++) {
00206                         size_t     len;
00207 
00208                         len = aux_ext_data->string_list[i].length
00209                                 * sizeof (CARD16);
00210                         total += ((sizeof (CARD16) + len + 3) / 4) * 4;
00211                 }
00212 
00213                 /*
00214                  * "+1" is required by mb_utf16() method.
00215                  * The method uses the area for BOM.
00216                  */
00217                 total += sizeof (CARD16);
00218         }
00219 
00220         string_buf = (char *)malloc(total);
00221         if (string_buf == NULL) {
00222                 return NULL;
00223         }
00224 
00225         XS_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
00226         XS_PROP_IMID(string_buf) = aux_ext_data->im;
00227         XS_PROP_ICID(string_buf) = aux_ext_data->ic;
00228 
00229         XS_PROP_INT_COUNT(string_buf) = aux_ext_data->integer_count;
00230         XS_PROP_STR_COUNT(string_buf) = aux_ext_data->string_count;
00231 
00232         ip = (int *)XS_PROP_INT_LIST(string_buf);
00233 
00234         if (aux_ext_data->integer_count > 0) {
00235                 for (i = 0; i < aux_ext_data->integer_count; i++) {
00236                         *ip++ = aux_ext_data->integer_list[i];
00237                 }
00238         }
00239 
00240         sp = (char *)XS_PROP_STR_LIST(string_buf);
00241 
00242         if (aux_ext_data->string_count > 0) {
00243                 char *             ob;
00244                 size_t             obl;
00245 
00246                 ob = sp;
00247 
00248                 for (i = 0; i < aux_ext_data->string_count; i++) {
00249                         size_t            len;
00250                         int        pn;
00251                         unsigned char     *p;
00252                         size_t            j;
00253 
00254                         len = aux_ext_data->string_list[i].length;
00255                         p = aux_ext_data->string_list[i].ptr;
00256 
00257                         *(CARD16 *)ob = len;
00258                         ob += sizeof (CARD16);
00259 
00260                         for (j = 0; j < len; j++) {
00261                                 *ob++ = *p++;
00262                         }
00263 
00264                         pn = padding[(sizeof (CARD16) + len) % 4];
00265 
00266                         /* padding */
00267                         for (j = 0; j < pn; j++) {
00268                                 *ob++ = 0U;
00269                         }
00270                         sp = ob;
00271                 }
00272         }
00273 
00274         *string_len = sp - &(string_buf[0]);
00275         return (string_buf);
00276 }
00277 
00278 static aux_ext_data_t *xaux_ext_decompose_from_string(xaux_class_t *xc, unsigned char *string_buf)
00279 {
00280         int          i;
00281         XPoint              point;
00282         aux_ext_data_t      *aux_ext_data;
00283 
00284         aux_ext_data = (aux_ext_data_t *)calloc(1, sizeof(aux_ext_data_t));
00285         if (aux_ext_data == NULL)
00286                 return NULL;
00287 
00288         /* header */
00289 
00290         aux_ext_data->type = AUX_EXT_DATA_DRAW;
00291         aux_ext_data->im = SX_PROP_IMID(string_buf);
00292         aux_ext_data->ic = SX_PROP_ICID(string_buf);
00293         aux_ext_data->aux_index = xc->index;
00294         aux_ext_data->aux_name = (unsigned char *)xc->classname;
00295         aux_ext_data->aux_name_length =
00296                 strlen((const char *)aux_ext_data->aux_name);
00297 
00298         /* int values */
00299 
00300         aux_ext_data->integer_count = SX_PROP_INT_COUNT(string_buf);
00301 
00302         if (aux_ext_data->integer_count > 0) {
00303                 aux_ext_data->integer_list =
00304                         (int *)SX_PROP_INT_LIST(string_buf);
00305         } else {
00306                 aux_ext_data->integer_list = NULL;
00307         }
00308 
00309         /* string values */
00310 
00311         aux_ext_data->string_count = SX_PROP_STR_COUNT(string_buf);
00312 
00313         DEBUG_printf("aux_ext_data->integer_count: %d\n", aux_ext_data->integer_count);
00314         DEBUG_printf("aux_ext_data->string_count: %d\n", aux_ext_data->string_count);
00315         if (aux_ext_data->string_count > 0) {
00316                 unsigned char * prop_str = SX_PROP_STR_LIST(string_buf);
00317 
00318                 if ((aux_ext_data->string_list =
00319                         (aux_ext_string_t *)malloc(sizeof (aux_ext_string_t) *
00320                                 aux_ext_data->string_count)) == NULL) {
00321                                 free ((char *)aux_ext_data);
00322                                 return NULL;
00323                 }
00324 
00325                 for(i = 0; i < aux_ext_data->string_count; i++) {
00326                         char *            ib;
00327                         size_t            ibl;
00328 
00329                         /* assign length of a string to ibl */
00330                         ibl = (size_t)*((CARD16 *)(prop_str));
00331                         /* move prop_str to point head of the string */
00332                         prop_str += sizeof(CARD16);
00333                         /* assign head of the string to ib */
00334                         ib = (char *)prop_str;
00335                         /* move prop_str to point lenght of next string */
00336                         prop_str += (ibl + padding[(sizeof(CARD16) + ibl) % 4]);
00337 
00338                         aux_ext_data->string_list[i].ptr = (unsigned char *)ib;
00339                         aux_ext_data->string_list[i].length = ibl;
00340                 }
00341         } else {
00342                 aux_ext_data->string_list = NULL;
00343         }
00344 
00345         aux_ext_data->string_ptr = NULL;
00346 
00347         aux_ext_data->clientwin = SX_PROP_CLIENTWIN(string_buf);
00348         aux_ext_data->point.x = SX_PROP_POSX(string_buf);
00349         aux_ext_data->point.y = SX_PROP_POSY(string_buf);
00350         aux_ext_data->focuswin = SX_PROP_FOCUSWIN(string_buf);
00351 
00352         return (aux_ext_data);
00353 }
00354 
00355 /************************************************************
00356     Send messages to aux object
00357 ************************************************************/
00358 static Bool
00359 xaux_ext_send_message(
00360         Display *    display,
00361         xaux_class_t *      xc,
00362         int          im_id,
00363         int          ic_id,
00364         aux_ext_data_type_t type,
00365         Atom         atom)
00366 {
00367         XClientMessageEvent event;
00368 
00369         if (xaux_ext_get_sowin(xc, display) == False) {
00370                 return False;
00371         }
00372 
00373         event.type = ClientMessage;
00374         event.serial = 0;
00375         event.send_event = True;
00376         event.display = display;
00377         event.window = xc->sowin;
00378         event.message_type = xc->atom_xs[0];
00379         event.format = 32;
00380 
00381         event.data.l[0] = xc->atom_classname;
00382         event.data.l[1] = ((CARD16)im_id << 8) | ((CARD16)ic_id & 0xffff);
00383         event.data.l[2] = xc->index;
00384         event.data.l[3] = type;
00385         if (type == AUX_EXT_DATA_SETVALUE) {
00386                 event.data.l[4] = atom;
00387         } else {
00388                 event.data.l[4] = 0; /* unused */
00389         }
00390 
00391         XSendEvent(display, xc->sowin, True, 0, (XEvent *)(&event));
00392 
00393         XFlush(display);
00394 
00395         return True;
00396 }
00397 
00398 static Bool
00399 xaux_ext_send_property(
00400         Display *           display,
00401         xaux_class_t *             xc,
00402         int                 im_id,
00403         int                 ic_id,
00404         const unsigned char *      p,
00405         int                 len)
00406 {
00407         DEBUG_printf("xaux_ext_send_property: xc: %p, len: %d\n", xc, len);
00408 
00409         if (xaux_ext_get_sowin(xc, display) == False) {
00410                 return False;
00411         }
00412 
00413         XChangeProperty(display, xc->sowin,
00414                 xc->atom_xs[xc->atom_xs_idx], XA_STRING,
00415                 8, PropModeReplace, (unsigned char *)p, len);
00416 
00417         if (xaux_ext_send_message(display, xc, im_id, ic_id,
00418                 AUX_EXT_DATA_SETVALUE, xc->atom_xs[xc->atom_xs_idx]) == False) {
00419                         return False;
00420         }
00421 
00422         /* XFlush() has been called in xaux_ext_send_message() */
00423 
00424         if (++xc->atom_xs_idx == xc->atom_xs_num)
00425                 xc->atom_xs_idx = 1;
00426 
00427         return True;
00428 }
00429 
00430 Bool
00431 xaux_ext_SetValue(
00432         Display             *display,
00433         xaux_class_t *xc,
00434         aux_ext_data_t      *aux_ext_data)
00435 {
00436     char  *string_buf = NULL;
00437     int         string_len;
00438     Bool  rv = True;
00439 
00440     aux_ext_data_t* aedata = NULL;
00441 
00442     if (aux_ext_data == NULL || xc == NULL) {
00443         return True;
00444     }
00445 
00446     DEBUG_printf("ext_SetValue[%s] im:0x%x ic:0x%x in=%d sn=%d\n",
00447                   xc->classname, aux_ext_data->im, aux_ext_data->ic,
00448                   aux_ext_data->integer_count, aux_ext_data->string_count);
00449 
00450     if (aux_ext_data->integer_count != 0 ||aux_ext_data->string_count != 0) {
00451 
00452         aedata = convertAuxExtData(aux_ext_data, 1);  //utf8->utf16
00453         string_buf = (char *)xaux_ext_compose_aux_ext_data(xc, aedata, &string_len);
00454 
00455         if (string_buf) {
00456             rv = xaux_ext_send_property(display, xc,
00457                                         aedata->im, aedata->ic,
00458                                         (unsigned char *)string_buf, string_len);
00459 
00460             free(string_buf);
00461         } else
00462             rv = True;
00463         freeConvertedAuxExtData(aedata);
00464     }
00465 
00466     return (rv);
00467 }
00468 
00469 /************************************************************
00470     Receive messages from aux object
00471 ************************************************************/
00472 static Bool
00473 xaux_ext_process_property_update(
00474         Display      *             display,
00475         Window                     window,
00476         Atom                message_type,
00477         Atom                atom)
00478 {
00479         Atom         actual_type_return;
00480         int          actual_format_return;
00481         unsigned long       nitem_return;
00482         unsigned long       bytes_after_return;
00483         unsigned char *     prop_return;
00484         int          r;
00485         Bool         rv;
00486         int          type;
00487         aux_ext_data_t      *aux_ext_data, *aedata;
00488         xaux_class_t *xc = &xaux_class;
00489 
00490         DEBUG_printf("xaux_ext_process_property_update ===================\n");
00491         if (window != xc->extwin && window != xc->sowin) {
00492                 return False;
00493         }
00494 
00495         r = XGetWindowProperty(display, window,
00496                                atom, 0, INT_MAX, False,
00497                                AnyPropertyType, &actual_type_return,
00498                                &actual_format_return, &nitem_return,
00499                                &bytes_after_return, &prop_return);
00500 
00501         if (r != Success || actual_type_return == 0) {
00502                 return False;
00503         }
00504 
00505         aux_ext_data = xaux_ext_decompose_from_string(xc, prop_return);
00506         if (aux_ext_data == NULL) {
00507                 XFree(prop_return);
00508                 return False;
00509         }
00510 
00511         type = SX_PROP_TYPE(prop_return);
00512 
00513         aedata = convertAuxExtData(aux_ext_data, 0); //UTF16->UTF8
00514 
00515         if (type == AUX_EXT_DATA_START) {
00516             DEBUG_printf("[%s] received START via property\n", xc->classname);
00517             rv = xaux_ext_Start(xc, aedata, message_type);
00518         } else if (type == AUX_EXT_DATA_DONE) {
00519             DEBUG_printf("[%s] received DONE via property\n", xc->classname);
00520             rv = xaux_ext_Done(xc, aedata, message_type);
00521         } else if (type == AUX_EXT_DATA_DRAW) {
00522             DEBUG_printf("[%s] received DRAW via property\n", xc->classname);
00523             rv = xaux_ext_Draw(xc, aedata, message_type);
00524         }
00525         freeConvertedAuxExtData(aedata);
00526 
00527         free(aux_ext_data->string_list);
00528         free(aux_ext_data);
00529         XFree(prop_return);
00530 
00531         return rv;
00532 }
00533 
00534 Bool
00535 xaux_ext_process_client_message(
00536         Display      *             display,
00537         XClientMessageEvent *      event)
00538 {
00539         aux_ext_data_t      aux_ext_data_;
00540         aux_ext_data_t      *aux_ext_data = &(aux_ext_data_);
00541         aux_ext_data_type_t type;
00542         xaux_class_t *xc = &xaux_class;
00543 
00544         if (event->data.l[0] != xc->atom_classname) {
00545                 return False;
00546         }
00547 
00548         if (event->window != xc->extwin) {
00549                 return False;
00550         }
00551 
00552         aux_ext_data->im = ((CARD32)(event->data.l[1])) >> 16;
00553         aux_ext_data->ic = ((CARD32)(event->data.l[1])) & 0xffff;
00554         aux_ext_data->aux_index = (CARD32)(event->data.l[2]);
00555 
00556         type = (CARD32)(event->data.l[3]);
00557 
00558         switch (type) {
00559         case AUX_EXT_DATA_START:
00560                 DEBUG_printf("[%s] received START via ClientMessage\n",
00561                         xc->classname);
00562                 return xaux_ext_Start(xc, aux_ext_data,(Atom)(CARD32)(event->message_type));
00563                 break;
00564         case AUX_EXT_DATA_DRAW:
00565                 DEBUG_printf("[%s] notified DRAW via ClientMessage\n",
00566                         xc->classname);
00567                 return xaux_ext_process_property_update(
00568                         display, xc->extwin, (Atom)(CARD32)(event->message_type), (Atom)(CARD32)(event->data.l[4]));
00569         case AUX_EXT_DATA_DONE:
00570                 DEBUG_printf("[%s] received DONE via ClientMessage\n",
00571                         xc->classname);
00572                 return xaux_ext_Done(xc, aux_ext_data,(Atom)(CARD32)(event->message_type));
00573                 break;
00574         default:
00575                 return False;
00576         }
00577 }
00578