| 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 &"
}
|