为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

xlib-programming

2012-11-15 41页 pdf 218KB 63阅读

用户头像

is_073869

暂无简介

举报
xlib-programming Basic Graphics Programming With The Xlib Library 1. Preface 2. The Client And Server Model Of The X Window System 3. GUI programming - the Asynchronous Programming Model 4. Basic Xlib Notions 1. The X Display 2. The GC - Graphics Context 3. Obj...
xlib-programming
Basic Graphics Programming With The Xlib Library 1. Preface 2. The Client And Server Model Of The X Window System 3. GUI programming - the Asynchronous Programming Model 4. Basic Xlib Notions 1. The X Display 2. The GC - Graphics Context 3. Object Handles 4. Memory Allocation For Xlib Structures 5. Events 5. Compiling Xlib-Based Programs 6. Opening And Closing The Connection To An X Server 7. Checking Basic Information About A Display 8. Creating A Basic Window - Our "hello world" Program 9. Drawing In A Window 1. Allocating A Graphics Context (GC) 2. Drawing Primitives - Point, Line, Box, Circle... 10.X Events 1. Registering For Event Types Using Event Masks 2. Receiving Events - Writing The Events Loop 3. Expose Events 4. Getting User Input 1. Mouse Button Click And Release Events 2. Mouse Movement Events 3. Mouse Pointer Enter And Leave Events 4. The Keyboard Focus 5. Keyboard Press And Release Events 5. X Events - A Complete Example 11.Handling Text And Fonts 1. The Font Structure 2. Loading A Font 3. Assigning A Font To A Graphics Context 4. Drawing Text In A Window 12.Windows Hierarchy 1. Root, Parent And Child Windows 2. Events Propagation 13.Interacting With The Window Manager 1. Window Properties 2. Setting The Window Name And Icon Name 3. Setting Preferred Window Size(s) 4. Setting Miscellaneous Window Manager Hints 5. Setting An Application's Icon 14.Simple Window Operations 1. Mapping And UN-Mapping A Window 2. Moving A Window Around The Screen 3. Resizing A Window 4. Changing Windows Stacking Order - Raise And Lower 5. Iconifying And De-Iconifying A Window 6. Getting Info About A Window 15.Using Colors To Paint The Rainbow 1. Color Maps 2. Allocating And Freeing Color Maps 3. Allocating And Freeing A Color Entry 4. Drawing With A Color 16.X Bitmaps And Pixmaps 1. What Is An X Bitmap? An X Pixmap? 2. Loading A Bitmap From A File 3. Drawing A Bitmap In A Window 4. Creating A Pixmap 5. Drawing A Pixmap In A Window 6. Freeing A Pixmap 17.Messing With The Mouse Cursor 1. Creating And Destroying A Mouse Cursor 2. Setting A Window's Mouse Cursor Preface This tutorial is the first in a series of "would-be" tutorials about graphical programming in the X window environment. By itself, it is useless. A real X programmer usually uses a much higher level of abstraction, such as using Motif (or its free version, lesstiff), GTK, QT and similar libraries. However, we need to start somewhere. More than this, knowing how things work down below is never a bad idea. After reading this tutorial, one would be able to write very simple graphical programs, but not programs with a descent user interface. For such programs, one of the previously mentioned libraries would be used. The Client And Server Model Of The X Window System The X window system was developed with one major goal - flexibility. The idea was that the way things look is one thing, but the way things work is another matter. Thus, the lower levels provide the tools required to draw windows, handle user input, allow drawing graphics using colors (or black and white screens), etc. To this point, a decision was made to separate the system into two parts. A client that decides what to do, and a server that actually draws on the screen and reads user input in order to send it to the client for processing. This model is the complete opposite of what one is used to when dealing with clients and servers. In our case, the user seats near the machine controlled by the server, while the client might be running on a remote machine. The server controls the screen, mouse and keyboard. A client may connect to the server, request that it draws a window (or several windows), and ask the server to send it any input the user sends to these windows. Thus, several clients may connect to a single X server - one might be running an email software, one running a WWW browser, etc. When input it sent by the user to some window, the server sends a message to the client controlling this window for processing. The client decides what to do with this input, and sends the server requests for drawing in the window. The whole session is carried out using the X message protocol. This protocol was originally carried over the TCP/IP protocol suite, allowing the client to run on any machine connected to the same network that the server is. Later on the X servers were extended to allow clients running on the local machine more optimized access to the server (note that an X protocol message may be several hundreds of KB in size), such as using shared memory, or using Unix domain sockets (a method for creating a logical channel on a Unix system between two processes). GUI programming - the Asynchronous Programming Model Unlike conventional computer programs, that carry some serial nature, a GUI program usually uses an asynchronous programming model, also known as "event-driven programming". This means that that program mostly sits idle, waiting for events sent by the X server, and then acts upon these events. An event may say "The user pressed the 1st button mouse in spot x,y", or "the window you control needs to be redrawn". In order for the program to be responsive to the user input, as well as to refresh requests, it needs to handle each event in a rather short period of time (e.g. less than 200 milliseconds, as a rule of thumb). This also implies that the program may not perform operations that might take a long time while handling an event (such as opening a network connection to some remote server, or connecting to a database server, or even performing a long file copy operation). Instead, it needs to perform all these operations in an asynchronous manner. This may be done by using various asynchronous models to perform the longish operations, or by performing them in a different process or thread. So the way a GUI program looks is something like that: 1. Perform initialization routines. 2. Connect to the X server. 3. Perform X-related initialization. 4. While not finished: 1. Receive the next event from the X server. 2. handle the event, possibly sending various drawing requests to the X server. 3. If the event was a quit message, exit the loop. 5. Close down the connection to the X server. 6. Perform cleanup operations. Basic Xlib Notions In order to eliminate the needs of programs to actually implement the X protocol layer, a library called 'Xlib' was created. This library gives a program a very low-level access to any X server. Since the protocol is standardized, A client using any implementation of Xlib may talk with any X server. This might look trivial these days, but back at the days of using character mode terminals and proprietary methods of drawing graphics on screens, this looked like a major break-through. In fact, you'll notice the big hype going around thin-clients, windows terminal servers, etc. They are implementing today what the X protocol enabled in the late 80's. On the other hand, the X universe is playing a catch-up game regarding CUA (common user access, a notion made by IBM to refer to the usage of a common look and feel for all programs in order to ease the lives of the users). Not having a common look and feel was a philosophy of the creators of the X window system. Obviously, it had some drawbacks that are evident today. The X Display The major notion of using Xlib is the X display. This is a structure representing the connection we have open with a given X server. It hides a queue of messages coming from the server, and a queue of pending requests that our client intends to send to the server. In Xlib, this structure is named 'Display'. When we open a connection to an X server, the library returns a pointer to such a structure. Later, we supply this pointer to any Xlib function that should send messages to the X server or receive messages from this server. The GC - Graphics Context When we perform various drawing operations (graphics, text, etc), we may specify various options for controlling how the data will be drawn - what foreground and background colors to use, how line edges will be connected, what font to use when drawing some text, etc). In order to avoid the need to supply zillions of parameters to each drawing function, a graphical context structure, of type 'GC' is used. We set the various drawing options in this structure, and then pass a pointer to this structure to any drawing routines. This is rather handy, as we often needs to perform several drawing requests with the same options. Thus, we would initialize a graphical context, set the desired options, and pass this GC structure to all drawing functions. Object Handles When various objects are created for us by the X server - such as windows, drawing areas and cursors - the relevant function returns a handle. This is some identifier for the object that actually resides in the X server's memory - not in our application's memory. We can later manipulate this object by supplying this handle to various Xlib functions. The server keeps a mapping between these handles and the actual objects it manages. Xlib provides various type definitions for these objects (Window, Cursor, Colormap and so on), which are all eventually mapped to simple integers. We should still use these type names when defining variables that hold handles - for portability reasons. Memory Allocation For Xlib Structures Various structure types are used in Xlib's interface. Some of them are allocated directly by the user. Others are allocated using specific Xlib functions. This allows the library to initialize properly these structures. This is very handy, since these structures tend to contain a lot of variables, making it rather tedious for the poor programmer to initialize. Remember - Xlib tries to be as flexible as possible, and this means it is also as complex as it can get. Having default values will enable a beginner X programmer to use the library, without interfering with the ability of a more experienced programmer to tweak with these zillions of options. As for freeing memory, this is done in one of two ways. In cases where we allocated the memory - we free it in the same manner (i.e. use free() to free memory allocated using malloc()). In case we used some Xlib function to allocate it, or we used some Xlib query method that returns dynamically allocated memory - we will use the XFree() function to free this memory block. Events A structure of type 'XEvent' is used to pass events received from the X server. Xlib supports a large amount of event types. The XEvent structure contains the type of event received, as well as the data associated with the event (e.g. position on the screen where the event was generated, mouse button associated with the event, region of screen associated with a 'redraw' event, etc). The way to read the event's data depends on the event type. Thus, an XEvent structure contains a C language union of all possible event types (if you're not sure what C unions are, it is time to check your proffered C language manual...). Thus, we could have an XExpose event, an XButton event, an XMotion event, etc. Compiling Xlib-Based Programs Compiling Xlib-Based programs requires linking them with the Xlib library. This is done using a compilation command like this: cc prog.c -o prog -lX11 If the compiler complains that it cannot find the X11 library, try adding a '-L' flag, like this: cc prog.c -o prog -L/usr/X11/lib -lX11 or perhaps this (for a system with release 6 of X11): cc prog.c -o prog -L/usr/X11R6/lib -lX11 On SunOs 4 systems, the X libraries are placed in /usr/openwin/lib: cc prog.c -o prog -L/usr/openwin/lib -lX11 and so on... Opening And Closing The Connection To An X Server An X program first needs to open the connection to the X server. When we do that, we need to specify the address of the host running the X server, as well as the display number. The X window system can support several displays all connected to the same machine. However, usually there is only one such display, which is display number '0'. If we wanted to connect to the local display (i.e. the display of the machine on which our client program runs), we could specify the display as ":0". To connect to the first display of a machine whose address is "simey", we could use the address "simey:0". Here is how the connection is opened: #include /* defines common Xlib functions and structs. */ . . /* this variable will contain the pointer to the Display structure */ /* returned when opening a connection. */ Display* display; /* open the connection to the display "simey:0". */ display = XOpenDisplay("simey:0"); if (display == NULL) { fprintf(stderr, "Cannot connect to X server %s\n", "simey:0"); exit (-1); } Note that is common for X programs to check if the environment variable 'DISPLAY' is defined, and if it is, use its contents as the parameter to the XOpenDisplay() function. When the program finished its business and needs to close the connection the X server, it does something like this: XCloseDisplay(display); This would cause all windows created by the program (if any are left) to be automatically closed by the server, and any resources stored on the server on behalf of the clients - to be freed. Note that this does not cause our client program to terminate - we could use the normal exit() function to do that. Checking Basic Information About A Display Once we opened a connection to an X server, we should check some basic information about it: what screens it has, what is the size (width and height) of the screen, how many colors it supports (black and white? grey scale? 256 colors? more?), and so on. We will show a code snippet that makes few of these checks, with comments explaining each function as it is being used. We assume that 'display' is a pointer to a 'Display' structure, as returned by a previous call to XOpenDisplay(). /* this variable will be used to store the "default" screen of the */ /* X server. usually an X server has only one screen, so we're only */ /* interested in that screen. */ int screen_num; /* these variables will store the size of the screen, in pixels. */ int screen_width; int screen_height; /* this variable will be used to store the ID of the root window of our */ /* screen. Each screen always has a root window that covers the whole */ /* screen, and always exists. */ Window root_window; /* these variables will be used to store the IDs of the black and white */ /* colors of the given screen. More on this will be explained later. */ unsigned long white_pixel; unsigned long black_pixel; /* check the number of the default screen for our X server. */ screen_num = DefaultScreen(display); /* find the width of the default screen of our X server, in pixels. */ screen_width = DisplayWidth(display, screen_num); /* find the height of the default screen of our X server, in pixels. */ screen_height = DisplayHeight(display, screen_num); /* find the ID of the root window of the screen. */ root_window = RootWindow(display, screen_num); /* find the value of a white pixel on this screen. */ white_pixel = WhitePixel(display, screen_num); /* find the value of a black pixel on this screen. */ black_pixel = BlackPixel(display, screen_num); There are various other macros to get more information about the screen, that you can find in any Xlib reference. There are also function equivalents for some of these macros (e.g. XWhitePixel, which does the same as WhitePixel). Creating A Basic Window - Our "hello world" Program After we got some basic information about our screen, we can get to creating our first window. Xlib supplies several functions for creating new windows, one of which is XCreateSimpleWindow(). This function gets quite a few parameters determining the window's size, its position, and so on. Here is a complete list of these parameters: Display* display Pointer to the Display structure. Window parent The ID of an existing window that should be the parent of the new window. int x X Position of the top-left corner of the window (given as number of pixels from the left of the screen). int y Y Position of the top-left corner of the window (given as number of pixels from the top of the screen). unsigned int width Width of the new window, in pixels. unsigned int height Height of the new window, in pixels. unsigned int border_width Width of the window's border, in pixels. unsigned long border Color to be used to paint the window's border. unsigned long background Color to be used to paint the window's background. Lets create a simple window, whose width is 1/3 of the screen's width, height is 1/3 of the screen's height, background color is white, border color is black, and border width is 2 pixels. The window will be placed at the top-left corner of the screen. /* this variable will store the ID of the newly created window. */ Window win; /* these variables will store the window's width and height. */ int win_width; int win_height; /* these variables will store the window's location. */ int win_x; int win_y; /* calculate the window's width and height. */ win_width = DisplayWidth(display, screen_num) / 3; win_height = DisplayHeight(display, screen_num) / 3; /* position of the window is top-left corner - 0,0. */ win_x = win_y = 0; /* create the window, as specified earlier. */ win = XCreateSimpleWindow(display, RootWindow(display, screen_num), win_x, win_y, win_width, win_height, win_border_width, BlackPixel(display, screen_num), WhitePixel(display, screen_num)); The fact that we created the window does not mean it will be drawn on screen. By default, newly created windows are not mapped on the screen - they are invisible. In order to make our window visible, we use the XMapWindow() function, as follows: XMapWindow(display, win); To see all the code we have gathered so far, take a look at the simple-window.c program. You'll see two more function not explained so far - XFlush() and XSync(). The XFlush() function flushes all pending requests to the X server - much like the fflush() function is used to flash standard output. The XSync() function also flushes all pending requests to the X server, and then waits until the X server finishes processing these requests. In a normal program this will not be necessary (you'll see why when we get to write a normal X program), but for now we put it there. Try compiling the program either with or without these function calls to see the difference in its behavior. Drawing In A Window Drawing in a window can be done using various graphical functions - drawing pixels, lines, circles, rectangles, etc. In order to draw in a window, we first need to define various general drawing parameters - what line width to use, which color to draw with, etc. This is done using a graphical context (GC). Allocating A Graphics Context (GC) As we said, a graphical context defines several attributes to be used with the various drawing functions. For this, we define a graphical context. We can use more than one graphical context with a single window, in order to draw in multiple styles (different colors, different line widths, etc.). Allocating a new GC is done using the XCreateGC() function, as follows (in this code fragment, we
/
本文档为【xlib-programming】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索