1.1 はじめに |
システムによって解決方法は変わるので、一概にどれがいいとは言えませんが、 今回の要求は:
ATOMを使った理由はXアプリケーション間の通信としてはそれが最も簡単だったこと、
また独立したプログラムpopupとしたのはポータビリティの確保のためです(ウインドウマネージャに組み込むことも可能だが、ポータビリティが失われる)。
Remark: さらにいえば、このような機能を有するウインドウマネージャが存在するかもしれないが、少くとも組み込み用途で使える軽量ウインドウマネージャには、この機能を有するものが見当たらなかった。
たぶん、ここに書かれた情報が必要な人間は世界中で10人もいないと思いますが、
私個人の備忘録として、ここに記述しておきます。
1.2 画面の配置を変更する: popup.c |
このプログラムのポイントは、
ATOMで画面IDを得る部分と、
関数XRaiseWindow()実行後、dummy loopとsignalの合わせ技でプログラム終了までに1秒の猶予を得る部分です。
後者について追記すると、
もしも1秒程度の猶予なく即座にプログラムを終了させた場合、画面が最上位に配置されません。
また、1秒の猶予を得るためにsleep()は使えません。あくまでプログラムがactiveな状態のまま1秒程度の
猶予が必要なのです。
/* ** Usage: popup ATOM_NAME */ #include <unistd.h> #include <signal.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <stdio.h> #include <stdlib.h> static void sig_alrm (int signo) { exit (0); } int main (int argc, char **argv) { Display *d; Window *w; Atom a, type; XEvent e; int fmt; unsigned long nitems, left; if (argc != 2) exit (-1); /* 1秒後、dummy loop中でsig_alrm()起動 */ if (signal (SIGALRM, sig_alrm) != SIG_ERR) alarm(1); /* ** 処理の本体 */ d = XOpenDisplay (NULL); a = XInternAtom (d, argv[1], False); if (XGetWindowProperty (d, RootWindow (d, 0), a, 0, 4, False, XA_WINDOW, &type, &fmt, &nitems, &left, (unsigned char **)&w) == Success && type == XA_WINDOW) { /* 画面を最上位に配置 */ XRaiseWindow (d, *w); } /* ** dummy loop: signalで設定したアラーム待ち -> 終了 */ while (1) XNextEvent (d, &e); return 0; } |
コンパイルは次のようにします。
コンパイルが終了したら、適当なディレクトリに移動しておきます。
今回は/usr/sbinに移動します。
1.3 アプリケーション側の設定 |
1.3.1 Xアプリケーション
最上位に配置したい画面に対して行う処理を示します。 これは、ごく普通のATOMの設定手順です。#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> ... 略 ... int main (int argc, char **argv) { Display *d; GC gc; Window w; Atom a; XEvent e; int x, y; d = XOpenDisplay (NULL); w = XCreateSimpleWindow (d, RootWindow (d, 0), 400, 400, 200, 200, 2, 0, 1); XMapWindow (d, w); gc = XCreateGC (d, w, 0, 0); /* ** ATOM"POPUP_X"の設定 */ /* ATOMの生成 */ a = XInternAtom (d, "POPUP_X", False); /* 念のため、プロパティを変更。以前に設定された同名のATOMがある場合への対処。*/ XChangeProperty (d, RootWindow (d, 0), a, XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1); ... 略 ... } |
1.3.2 Gtkアプリケーション
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <gdk/gdkx.h> /* ** ATOMの設定 */ static void atom_set (GtkWidget *window, const char *name) { GdkDisplay *d; Window xwindow; Atom a; d = gdk_drawable_get_display (window->window); xwindow = GDK_WINDOW_XID (window->window); a = XInternAtom (GDK_DISPLAY_XDISPLAY (d), name, False); XChangeProperty (GDK_DISPLAY_XDISPLAY (d), RootWindow (GDK_DISPLAY_XDISPLAY (d), 0), a, XA_WINDOW, 32, PropModeReplace, (unsigned char *)&xwindow, 1); } int main (int argc, char *argv[]) { ... 略 ... window1 = create_window1 (); gtk_widget_show (window1); window2 = create_window2 (); gtk_widget_show (window2); /* ** ATOMの設定 */ atom_set (window1, "POPUP_GTK"); atom_set (window2, "POPUP_GTK2"); gtk_main (); return 0; } |
1.4 実行方法 |
1.4.1 直接popupコマンドを実行
下図において、Xターミナルrxvtに隠れているXアプリケーションを、 最上位に配置してみます。
Remark: popupコマンドは、ウインドウマネージャmwmとGNOMEでは実行可能でしたが、 ウインドウマネージャxfceでは機能しませんでした。原因は不明です。
1.4.2 ウインドウマネージャから実行
ウインドウマネージャのなかには、コマンド起動を任意のキーにバインドできるものがあります。
mwmの設定ファイルは~/.mwmrc(もしくは/usr/X11R6/lib/mwm/system.mwmrc)です。
このファイルの"Keys DefaultKeyBindings"セクションに、キーバインドとpopupコマンドの実行文を記述すると、
キー操作一発で、指定した画面を最上位に配置させることが可能です。
この例では、F4キーを押すと"/usr/sbin/popup POPUP_X &"が、
F5キーを押すと"/usr/sbin/popup POPUP_GTK &"が、
Alt+Shift+Deleteキーを押すと"/usr/sbin/popup POPUP_GTK2 &"が、
それぞれ実行されます。
ここで注意すべき点は、/usr/sbin/popupをバックグランドで実行しなければならないことです。
Keys DefaultKeyBindings { ... 略 ... <Key>F4 root|icon|window f.exec "/usr/sbin/popup POPUP_X &" <Key>F5 root|icon|window f.exec "/usr/sbin/popup POPUP_GTK &" Alt Shift<Key>Delete root|icon|window f.exec "/usr/sbin/popup POPUP_GTK2 &" } |