x window panel from scratch
最近正在看怎麼寫一個x window上的panel, 也就順便看了一下Window Manager的架構, 在網路上找了一下, 覺的最好的範例是fbpanel (http://fbpanel.sourceforge.net/) , 有興趣的人可以自己下載source code回來看看.
接下來就來說說如何自己寫一個panel, 其實panel也是一個window, 只是他多了一些不一樣屬性, 在這裡我就用程式碼來說明 (以下的程式碼大部分都使用GTK+, 如果不喜歡GTK, 可以直接使用XLib, 或是任何Toolkit找到相對應的api就可以了, 觀念都一樣, 甚至連api名字都差不多)
首先建立一個windowGtkWidget* panel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
如同一般window一樣, panel也是一個TOPLEVEL的window,
將panel的decoration(視窗旁邊的裝飾)關掉,gtk_window_set_decorated( GTK_WINDOW( panel), FALSE );
接下來是一些比較簡單的屬性, resizable, position
gtk_window_set_resizable( GTK_WINDOW( panel), FALSE);
gtk_window_set_position( GTK_WINDOW( panel), GTK_WIN_POS_NONE);
之後的屬性就需要window被realized以後才能夠更改, 所以我們這裡要先realized
gtk_widget_realize(panel);
skip task bar hint就是讓window manager在taskbar上不顯示這個視窗(panel不會出現在taskbar是很正常的一件事)
gtk_window_set_skip_taskbar_hint( GTK_WINDOW( panel) , TRUE );
skip pager hint有個很好的例子, 當按下Alt-Tab出現window list, 他不會出現在裡面(panel不會出現在pager也是很正常的一件事)
gtk_window_set_skip_pager_hint( GTK_WINDOW( panel) , TRUE );
然後讓panel永遠比別人大...阿...是在別的視窗上面啦
gtk_window_set_keep_above( GTK_WINDOW( panel), TRUE);
每個desktop都要看得到panel
gtk_window_stick( GTK_WINDOW(panel));
跟window manager講說這是個dock type的window
gtk_window_set_type_hint ( GTK_WINDOW(panel), GDK_WINDOW_TYPE_HINT_DOCK);
設定panel的大小跟位置
gtk_widget_set_size_request(panel, gdk_screen_width(), 64);
gtk_window_move( GTK_WINDOW(panel), 0, gdk_screen_height() - 64);
你以為這樣就結束了嘛?
並沒有, 最後設定_NET_WM_STRUT這個HINT讓Window Manager知道panel已經用掉視窗邊邊的某個區域了, 格式為
_NET_WM_STRUT, left, right, top, bottom, CARDINAL[4]/32詳細請參照EWMH
你塞進去的資料假設為一個unsign long[4],第0個代表螢幕左邊保留的寬度,下面以此類推
另一個HINT是_NET_WM_STRUT_PARTIAL可以用來通知windowmanager你只要預留邊邊域的一部分就好
_NET_WM_STRUT_PARTIAL, left, right, top, bottom, left_start_y, left_end_y,
right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
bottom_end_x,CARDINAL[12]/32
gulong data[12] = { 0 };這樣就可以產生一個位在螢幕底部的panel, 裡面的東西就隨便你放啦
data[3] = 64;//_panel->allocation.height;
data[4 + 3*2] = _panel->allocation.x;
data[5 + 3*2] = _panel->allocation.x + _panel->allocation.width;
gdk_property_change( _panel->window,
gdk_atom_intern("_NET_WM_STRUT_PARTIAL",FALSE),
gdk_atom_intern ("CARDINAL", FALSE),
32, GDK_PROP_MODE_REPLACE, (unsigned char *)data, 12);
gdk_property_change( _panel->window,
gdk_atom_intern("_NET_WM_STRUT",FALSE),
gdk_atom_intern ("CARDINAL", FALSE),
32, GDK_PROP_MODE_REPLACE, (unsigned char *)data, 4);
No comments:
Post a Comment