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